Improved error handling for antlr3 and antlr4 trees:
- Error listeners and message formatters
- Cosmas grammar incorporates setter method for error listener
- No more QueryExceptions, instead return empty query serialization along with error msg
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/Antlr3DescriptiveErrorListener.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/Antlr3DescriptiveErrorListener.java
new file mode 100644
index 0000000..2a0fb63
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/Antlr3DescriptiveErrorListener.java
@@ -0,0 +1,85 @@
+package de.ids_mannheim.korap.query.serialize.util;
+
+import java.util.ArrayList;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.ids_mannheim.korap.query.cosmas2.IErrorReporter;
+import de.ids_mannheim.korap.query.serialize.QueryUtils;
+
+/**
+ * Custom descriptive error listener for Antlr3 grammars. Requires interface IErrorReporter to be present in
+ * grammar destination (generated source directory).
+ * @author Joachim Bingel (bingel@ids-mannheim.de)
+ *
+ */
+public class Antlr3DescriptiveErrorListener implements IErrorReporter {
+
+ private String query;
+ private String offendingSymbol;
+ private String expected;
+ private int charPosition;
+
+ public Antlr3DescriptiveErrorListener(String query) {
+ this.query = query;
+ };
+
+ @Override
+ public void reportError(String error) {
+ String charPositionStr = null;
+ String offendingSymbol = null;
+ String expected = null;
+ Pattern p = Pattern.compile("line \\d+:(\\d+).* '(.+?)' expecting (.+)");
+ Matcher m = p.matcher(error);
+ if (m.find()) {
+ charPositionStr = m.group(1);
+ offendingSymbol = m.group(2);
+ expected = m.group(3);
+ }
+ if (charPositionStr != null)
+ this.charPosition = Integer.parseInt(charPositionStr);
+ if (offendingSymbol != null)
+ this.offendingSymbol = offendingSymbol;
+ if (expected != null)
+ this.expected = expected;
+ }
+
+ public ArrayList<Object> generateFullErrorMsg() {
+ ArrayList<Object> errorSpecs = new ArrayList<Object>();
+ String msg = getDetailedErrorMessage();
+ errorSpecs.add(StatusCodes.MALFORMED_QUERY);
+ errorSpecs.add(msg);
+ errorSpecs.add(getCharPosition());
+ return errorSpecs;
+ }
+
+ private String getDetailedErrorMessage() {
+ // default message, in case no detailed info is available;
+ String msg = "Malformed query. Could not parse.";
+ char offendingSymbol = query.charAt(0);
+ if (query.length() > charPosition) offendingSymbol = query.charAt(charPosition);
+ msg = "Failing to parse at symbol: '"+offendingSymbol+"'";
+ if (expected != null) {
+ if (expected.equals("EOF") || expected.equals("<EOF>")) {
+ msg += " Expected end of query.";
+ } else {
+ msg += " Expected '"+expected+"'";
+ }
+ }
+ // check for unbalanced parantheses
+ SimpleEntry<String, Integer> unbalanced = QueryUtils.checkUnbalancedPars(query);
+ if (unbalanced != null) {
+ msg = unbalanced.getKey();
+ charPosition = unbalanced.getValue();
+ }
+
+ return msg;
+ }
+
+ public int getCharPosition() {
+ return charPosition;
+ }
+
+
+}
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/Antlr4DescriptiveErrorListener.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/Antlr4DescriptiveErrorListener.java
new file mode 100644
index 0000000..5b7115e
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/Antlr4DescriptiveErrorListener.java
@@ -0,0 +1,72 @@
+package de.ids_mannheim.korap.query.serialize.util;
+
+import java.util.ArrayList;
+import java.util.AbstractMap.SimpleEntry;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+
+import de.ids_mannheim.korap.query.serialize.QueryUtils;
+
+public class Antlr4DescriptiveErrorListener extends BaseErrorListener {
+
+ String query;
+ String message;
+ int line;
+ int charPosition;
+
+ public Antlr4DescriptiveErrorListener(String query) {
+ this.query = query;
+ };
+
+ @Override
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
+ int line, int charPositionInLine,
+ String msg, RecognitionException e)
+ {
+ this.message = msg;
+ this.line = line;
+ this.charPosition = charPositionInLine;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public int getLine() {
+ return line;
+ }
+
+ public int getCharPosition() {
+ return charPosition;
+ }
+
+ public ArrayList<Object> generateFullErrorMsg() {
+ ArrayList<Object> errorSpecs = new ArrayList<Object>();
+ String msg = getDetailedErrorMessage();
+ errorSpecs.add(StatusCodes.MALFORMED_QUERY);
+ errorSpecs.add(msg);
+ errorSpecs.add(getCharPosition());
+ return errorSpecs;
+ }
+
+ private String getDetailedErrorMessage() {
+ // default message, in case no detailed info is available;
+ String msg = "Malformed query. Could not parse.";
+ char offendingSymbol = query.charAt(0);
+ if (query.length() > charPosition) offendingSymbol = query.charAt(charPosition);
+ msg = "Failing to parse at symbol: '"+offendingSymbol+"'";
+ // check for unbalanced parantheses
+ SimpleEntry<String, Integer> unbalanced = QueryUtils.checkUnbalancedPars(query);
+ if (unbalanced != null) {
+ msg = unbalanced.getKey();
+ charPosition = unbalanced.getValue();
+ }
+
+ return msg;
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java b/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
new file mode 100644
index 0000000..6bcf7e9
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/query/serialize/util/StatusCodes.java
@@ -0,0 +1,10 @@
+package de.ids_mannheim.korap.query.serialize.util;
+
+public class StatusCodes {
+ public final static int NO_QUERY = 301;
+ public final static int MALFORMED_QUERY = 302;
+ public final static int DEPRECATED_QUERY_ELEMENT = 303;
+ public final static int UNDEFINED_CLASS_REFERENCE = 304;
+ public final static int INCOMPATIBLE_OPERATOR_AND_OPERAND = 305;
+ public final static int UNKNOWN_QUERY_ELEMENT = 306;
+}