From 1901b1d3513f1e84ea74ef319014153b51f6318d Mon Sep 17 00:00:00 2001
From: dgelessus <dgelessus@users.noreply.github.com>
Date: Wed, 25 Jan 2023 11:17:09 +0100
Subject: [PATCH] Split VOParseException into separate subclasses and make
 unchecked

Replaces the previous ErrorType enum. Separate classes are more
convenient for catch blocks and such.

Making the exceptions unchecked will allow throwing them from places
where checked exceptions cannot be used, e. g. SableCC AnalysisAdapter
methods.
---
 .../java/de/prob/voparser/VOException.java    | 17 +++++++++++++
 .../de/prob/voparser/VOParseException.java    | 24 +++++++++----------
 src/main/java/de/prob/voparser/VOParser.java  | 18 +++++++-------
 .../prob/voparser/VOScopeCheckException.java  | 17 +++++++++++++
 .../java/de/prob/voparser/VOScopeChecker.java |  4 ++--
 .../prob/voparser/VOTypeCheckException.java   | 17 +++++++++++++
 .../java/de/prob/voparser/VOTypeChecker.java  |  4 ++--
 .../java/de/prob/voparser/VOParserTest.java   | 12 +++++-----
 .../java/de/prob/voparser/VOScopingTest.java  | 20 ++++++++--------
 .../de/prob/voparser/VOTypeCheckingTest.java  | 12 +++++-----
 10 files changed, 97 insertions(+), 48 deletions(-)
 create mode 100644 src/main/java/de/prob/voparser/VOException.java
 create mode 100644 src/main/java/de/prob/voparser/VOScopeCheckException.java
 create mode 100644 src/main/java/de/prob/voparser/VOTypeCheckException.java

diff --git a/src/main/java/de/prob/voparser/VOException.java b/src/main/java/de/prob/voparser/VOException.java
new file mode 100644
index 0000000..918079a
--- /dev/null
+++ b/src/main/java/de/prob/voparser/VOException.java
@@ -0,0 +1,17 @@
+package de.prob.voparser;
+
+public class VOException extends RuntimeException {
+	private static final long serialVersionUID = 1L;
+	
+	public VOException(final String message, final Throwable cause) {
+		super(message, cause);
+	}
+	
+	public VOException(final String message) {
+		this(message, null);
+	}
+	
+	public VOException(final Throwable cause) {
+		this(cause == null ? null : cause.toString(), cause);
+	}
+}
diff --git a/src/main/java/de/prob/voparser/VOParseException.java b/src/main/java/de/prob/voparser/VOParseException.java
index 5f618c4..01cb83f 100644
--- a/src/main/java/de/prob/voparser/VOParseException.java
+++ b/src/main/java/de/prob/voparser/VOParseException.java
@@ -1,19 +1,17 @@
 package de.prob.voparser;
 
-public class VOParseException extends Exception {
-
-	public enum ErrorType {
-		PARSING, SCOPING, TYPECHECKING
+public class VOParseException extends VOException {
+	private static final long serialVersionUID = 1L;
+	
+	public VOParseException(final String message, final Throwable cause) {
+		super(message, cause);
 	}
-
-	private ErrorType errorType;
-
-	public VOParseException(String message, ErrorType errorType) {
-		super(message);
-		this.errorType = errorType;
+	
+	public VOParseException(final String message) {
+		this(message, null);
 	}
-
-	public ErrorType getErrorType() {
-		return errorType;
+	
+	public VOParseException(final Throwable cause) {
+		this(cause == null ? null : cause.toString(), cause);
 	}
 }
diff --git a/src/main/java/de/prob/voparser/VOParser.java b/src/main/java/de/prob/voparser/VOParser.java
index 09f6533..7eb0fac 100644
--- a/src/main/java/de/prob/voparser/VOParser.java
+++ b/src/main/java/de/prob/voparser/VOParser.java
@@ -26,11 +26,11 @@ public class VOParser {
 		this.typeChecker = new VOTypeChecker(this);
 	}
 
-	public Start parseFormula(String formula) throws VOParseException {
+	public Start parseFormula(String formula) {
 		return parseAST(formula);
 	}
 
-	public Start parseAST(String formula) throws VOParseException {
+	public Start parseAST(String formula) {
 		StringReader reader = new StringReader(formula);
 		PushbackReader r = new PushbackReader(reader);
 		Lexer l = new Lexer(r);
@@ -39,11 +39,11 @@ public class VOParser {
 		try {
 			ast = p.parse();
 		} catch (ParserException e) {
-			throw new VOParseException("Parsing VO formula failed at: " + e.getToken().getText(), VOParseException.ErrorType.PARSING);
+			throw new VOParseException("Parsing VO formula failed at: " + e.getToken().getText(), e);
 		} catch (IOException e) {
-			throw new VOParseException("Parsing VO formula failed", VOParseException.ErrorType.PARSING);
+			throw new VOParseException("Parsing VO formula failed", e);
 		} catch (LexerException e) {
-			throw new VOParseException("Parsing VO formula failed: " + e.getMessage(), VOParseException.ErrorType.PARSING);
+			throw new VOParseException("Parsing VO formula failed: " + e.getMessage(), e);
 		}
 		return ast;
 	}
@@ -56,22 +56,22 @@ public class VOParser {
 		tasks.remove(id);
 	}
 
-	public void semanticCheck(Start ast) throws VOParseException {
+	public void semanticCheck(Start ast) {
 		scopeChecker.scopeCheck(ast);
 		typeChecker.typeCheck(ast);
 	}
 
-	public void semanticCheck(String formula) throws VOParseException {
+	public void semanticCheck(String formula) {
 		scopeCheck(formula);
 		typeCheck(formula);
 	}
 
-	public void scopeCheck(String formula) throws VOParseException {
+	public void scopeCheck(String formula) {
 		Start start = parseFormula(formula);
 		scopeChecker.scopeCheck(start);
 	}
 
-	public void typeCheck(String formula) throws VOParseException {
+	public void typeCheck(String formula) {
 		Start start = parseFormula(formula);
 		typeChecker.typeCheck(start);
 	}
diff --git a/src/main/java/de/prob/voparser/VOScopeCheckException.java b/src/main/java/de/prob/voparser/VOScopeCheckException.java
new file mode 100644
index 0000000..7bbe7e2
--- /dev/null
+++ b/src/main/java/de/prob/voparser/VOScopeCheckException.java
@@ -0,0 +1,17 @@
+package de.prob.voparser;
+
+public class VOScopeCheckException extends VOException {
+	private static final long serialVersionUID = 1L;
+	
+	public VOScopeCheckException(final String message, final Throwable cause) {
+		super(message, cause);
+	}
+	
+	public VOScopeCheckException(final String message) {
+		this(message, null);
+	}
+	
+	public VOScopeCheckException(final Throwable cause) {
+		this(cause == null ? null : cause.toString(), cause);
+	}
+}
diff --git a/src/main/java/de/prob/voparser/VOScopeChecker.java b/src/main/java/de/prob/voparser/VOScopeChecker.java
index 88070e2..e6d97dc 100644
--- a/src/main/java/de/prob/voparser/VOScopeChecker.java
+++ b/src/main/java/de/prob/voparser/VOScopeChecker.java
@@ -16,10 +16,10 @@ public class VOScopeChecker extends DepthFirstAdapter {
 		this.error = false;
 	}
 
-	public void scopeCheck(Start start) throws VOParseException {
+	public void scopeCheck(Start start) {
 		start.apply(this);
 		if(error) {
-			throw new VOParseException("Scope error in VO", VOParseException.ErrorType.SCOPING);
+			throw new VOScopeCheckException("Scope error in VO");
 		}
 	}
 
diff --git a/src/main/java/de/prob/voparser/VOTypeCheckException.java b/src/main/java/de/prob/voparser/VOTypeCheckException.java
new file mode 100644
index 0000000..a0b0555
--- /dev/null
+++ b/src/main/java/de/prob/voparser/VOTypeCheckException.java
@@ -0,0 +1,17 @@
+package de.prob.voparser;
+
+public class VOTypeCheckException extends VOException {
+	private static final long serialVersionUID = 1L;
+	
+	public VOTypeCheckException(final String message, final Throwable cause) {
+		super(message, cause);
+	}
+	
+	public VOTypeCheckException(final String message) {
+		this(message, null);
+	}
+	
+	public VOTypeCheckException(final Throwable cause) {
+		this(cause == null ? null : cause.toString(), cause);
+	}
+}
diff --git a/src/main/java/de/prob/voparser/VOTypeChecker.java b/src/main/java/de/prob/voparser/VOTypeChecker.java
index 0288979..177a5b7 100644
--- a/src/main/java/de/prob/voparser/VOTypeChecker.java
+++ b/src/main/java/de/prob/voparser/VOTypeChecker.java
@@ -24,10 +24,10 @@ public class VOTypeChecker extends DepthFirstAdapter {
 		this.modifiedAnimatorState = PersistentHashSet.create(AnimatorState.STATE_SPACE, AnimatorState.TRACE);
 	}
 
-	public void typeCheck(Start start) throws VOParseException {
+	public void typeCheck(Start start) {
 		start.apply(this);
 		if (error) {
-			throw new VOParseException("Type error in VO", VOParseException.ErrorType.TYPECHECKING);
+			throw new VOTypeCheckException("Type error in VO");
 		}
 	}
 
diff --git a/src/test/java/de/prob/voparser/VOParserTest.java b/src/test/java/de/prob/voparser/VOParserTest.java
index 43fbe65..4e8956b 100644
--- a/src/test/java/de/prob/voparser/VOParserTest.java
+++ b/src/test/java/de/prob/voparser/VOParserTest.java
@@ -11,38 +11,38 @@ import org.junit.Test;
 public class VOParserTest {
 
 	@Test
-	public void testAtomic() throws VOParseException {
+	public void testAtomic() {
 		VOParser voParser = new VOParser();
 		voParser.parseFormula("MC1");
 	}
 
 	@Test
-	public void testSequential() throws VOParseException {
+	public void testSequential() {
 		VOParser voParser = new VOParser();
 		voParser.parseFormula("MC1;TR1");
 	}
 
 	@Test
-	public void testAnd() throws VOParseException {
+	public void testAnd() {
 		VOParser voParser = new VOParser();
 		voParser.parseFormula("MC1 & TR1");
 	}
 
 	@Test
-	public void testOr() throws VOParseException {
+	public void testOr() {
 		VOParser voParser = new VOParser();
 		voParser.parseFormula("MC1 or TR1");
 	}
 
 	@Test
-	public void testDot() throws VOParseException {
+	public void testDot() {
 		VOParser voParser = new VOParser();
 		voParser.parseFormula("MC.1");
 	}
 
 
 	@Test(expected = VOParseException.class)
-	public void testParseError() throws VOParseException {
+	public void testParseError() {
 		VOParser voParser = new VOParser();
 		voParser.parseFormula("MC.1;");
 	}
diff --git a/src/test/java/de/prob/voparser/VOScopingTest.java b/src/test/java/de/prob/voparser/VOScopingTest.java
index d033f72..2665b09 100644
--- a/src/test/java/de/prob/voparser/VOScopingTest.java
+++ b/src/test/java/de/prob/voparser/VOScopingTest.java
@@ -11,29 +11,29 @@ import org.junit.Test;
 public class VOScopingTest {
 
 	@Test
-	public void testAtomic() throws VOParseException {
+	public void testAtomic() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.EXPLORE);
 		voParser.scopeCheck("MC1");
 	}
 
 	@Test
-	public void testSequential() throws VOParseException {
+	public void testSequential() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.TRACE);
 		voParser.registerTask("TR1", VTType.TRACE);
 		voParser.scopeCheck("MC1;TR1");
 	}
 
-	@Test(expected = VOParseException.class)
-	public void testSequentialError() throws VOParseException {
+	@Test(expected = VOScopeCheckException.class)
+	public void testSequentialError() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.TRACE);
 		voParser.scopeCheck("MC1;TR1");
 	}
 
 	@Test
-	public void testAnd() throws VOParseException {
+	public void testAnd() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.TRACE);
 		voParser.registerTask("TR1", VTType.TRACE);
@@ -41,7 +41,7 @@ public class VOScopingTest {
 	}
 
 	@Test
-	public void testAnd2() throws VOParseException {
+	public void testAnd2() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1.1", VTType.TRACE);
 		voParser.registerTask("TR1.1", VTType.TRACE);
@@ -51,7 +51,7 @@ public class VOScopingTest {
 	}
 
 	@Test
-	public void testOr() throws VOParseException {
+	public void testOr() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.TRACE);
 		voParser.registerTask("TR1", VTType.TRACE);
@@ -59,15 +59,15 @@ public class VOScopingTest {
 	}
 
 	@Test
-	public void testDot() throws VOParseException {
+	public void testDot() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1.1", VTType.EXPLORE);
 		voParser.scopeCheck("MC1.1");
 	}
 
 
-	@Test(expected = VOParseException.class)
-	public void testScopingError() throws VOParseException {
+	@Test(expected = VOScopeCheckException.class)
+	public void testScopingError() {
 		VOParser voParser = new VOParser();
 		voParser.scopeCheck("MC1");
 	}
diff --git a/src/test/java/de/prob/voparser/VOTypeCheckingTest.java b/src/test/java/de/prob/voparser/VOTypeCheckingTest.java
index 16ed0c6..8d3eb82 100644
--- a/src/test/java/de/prob/voparser/VOTypeCheckingTest.java
+++ b/src/test/java/de/prob/voparser/VOTypeCheckingTest.java
@@ -11,22 +11,22 @@ import org.junit.Test;
 public class VOTypeCheckingTest {
 
 	@Test
-	public void testAtomic() throws VOParseException {
+	public void testAtomic() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.EXPLORE);
 		voParser.typeCheck("MC1");
 	}
 
 	@Test
-	public void testSequential() throws VOParseException {
+	public void testSequential() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.TRACE);
 		voParser.registerTask("MC2", VTType.EXPLORE);
 		voParser.typeCheck("MC1;MC2");
 	}
 
-	@Test(expected =  VOParseException.class)
-	public void testSequential2() throws VOParseException {
+	@Test(expected = VOTypeCheckException.class)
+	public void testSequential2() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.TRACE);
 		voParser.registerTask("MC2", VTType.TRACE);
@@ -35,7 +35,7 @@ public class VOTypeCheckingTest {
 	}
 
 	@Test
-	public void testAnd() throws VOParseException {
+	public void testAnd() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.TRACE);
 		voParser.registerTask("TR1", VTType.TRACE);
@@ -43,7 +43,7 @@ public class VOTypeCheckingTest {
 	}
 
 	@Test
-	public void testOr() throws VOParseException {
+	public void testOr() {
 		VOParser voParser = new VOParser();
 		voParser.registerTask("MC1", VTType.TRACE);
 		voParser.registerTask("TR1", VTType.TRACE);
-- 
GitLab