ParseException.java
/* Generated by: CongoCC Parser Generator. ParseException.java */
package de.schegge.rosinante.parser;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.*;
public class ParseException extends RuntimeException {
// The location where we tripped up.
private Node location;
//We were expecting one of these token types
private Set<? extends Node.NodeType> expectedTypes;
private List<NonTerminalCall> callStack = new ArrayList<>();
public ParseException(Node location, Set<? extends Node.NodeType> expectedTypes, List<NonTerminalCall> callStack) {
this.location = location;
this.expectedTypes = expectedTypes;
if (callStack != null) {
this.callStack = new ArrayList<>(callStack);
}
}
public ParseException(Node location) {
this.location = location;
}
public ParseException(String message) {
super(message);
}
public ParseException() {
super();
}
public ParseException(String message, List<NonTerminalCall> callStack) {
super(message);
if (callStack != null) {
this.callStack = new ArrayList<>(callStack);
}
}
public ParseException(String message, Node location, List<NonTerminalCall> callStack) {
super(message);
this.location = location;
if (callStack != null) {
this.callStack = new ArrayList<>(callStack);
}
}
public void printStackTrace(PrintStream ps) {
ps.println(getMessage());
ps.print(getCustomStackTrace());
}
public void printStackTrace(PrintWriter pw) {
pw.println(getMessage());
pw.print(getCustomStackTrace());
}
public void printJavaStackTrace(PrintStream ps) {
super.printStackTrace(ps);
}
public void printJavaStackTrace(PrintWriter pw) {
super.printStackTrace(pw);
}
public boolean hitEOF() {
return location != null && location.getType() != null && location.getType().isEOF();
}
private boolean javaLocationsFilledIn;
void fillInJavaCodeLocations() {
if (javaLocationsFilledIn) return;
List<StackTraceElement> stackTrace = new ArrayList<>();
for (StackTraceElement elem : getStackTrace()) {
stackTrace.add(elem);
}
List<NonTerminalCall> callStack = new ArrayList<>(this.callStack);
Collections.reverse(callStack);
while (!callStack.isEmpty()) {
NonTerminalCall ntc = callStack.remove(callStack.size() - 1);
while (!stackTrace.isEmpty()) {
StackTraceElement elem = stackTrace.remove(stackTrace.size() - 1);
if (elem.getMethodName().equals(ntc.productionName) && elem.getClassName().endsWith("." + ntc.parserClassName)) {
ntc.javaSourceLine = elem.getLineNumber();
break;
}
}
}
javaLocationsFilledIn = true;
}
@Override
public String getMessage() {
StringBuilder buf = new StringBuilder();
buf.append("Encountered an error");
if (location != null) {
buf.append(" at ");
buf.append(location.getLocation());
}
if (super.getMessage() != null) {
buf.append("\n");
buf.append(super.getMessage());
}
if (hitEOF()) {
buf.append("\nUnexpected end of input.");
}
if (location == null || location.getType() == null || expectedTypes == null || expectedTypes.contains(location.getType())) {
return buf.toString();
}
String content = location.toString();
if (content == null || content.length() == 0) {
buf.append("\n Found token of type " + location.getType());
} else {
if (content.length() > 32) content = content.substring(0, 32) + "...";
buf.append("\nFound string \"" + addEscapes(content) + "\" of type " + location.getType());
}
if (expectedTypes.size() == 1) {
buf.append("\nWas expecting: " + expectedTypes.iterator().next());
} else {
buf.append("\nWas expecting one of the following:\n");
boolean isFirst = true;
for (Node.NodeType type : expectedTypes) {
if (!isFirst) buf.append(", ");
isFirst = false;
buf.append(type);
}
}
return buf.toString();
}
// TODO: Make this configurable
public String getCustomStackTrace() {
fillInJavaCodeLocations();
StringBuilder buf = new StringBuilder();
for (int i = callStack.size() - 1; i >= 0; i--) {
buf.append(" ");
buf.append(callStack.get(i));
}
return buf.toString();
}
/**
* Returns the token which causes the parse error and null otherwise.
* @return the token which causes the parse error and null otherwise.
*/
public Node getLocation() {
return location;
}
/**
* @Deprecated Use #getLocation
* We just keep this around in case anybody using it.
*/
public Node getToken() {
return location;
}
private static String addEscapes(String str) {
StringBuilder retval = new StringBuilder();
for (int ch : str.codePoints().toArray()) {
switch(ch) {
case '\b' :
retval.append("\\b");
continue;
case '\t' :
retval.append("\\t");
continue;
case '\n' :
retval.append("\\n");
continue;
case '\f' :
retval.append("\\f");
continue;
case '\r' :
retval.append("\\r");
continue;
case '\"' :
retval.append("\\\"");
continue;
case '\'' :
retval.append("\\\'");
continue;
case '\\' :
retval.append("\\\\");
continue;
default :
if (Character.isISOControl(ch)) {
String s = "0000" + java.lang.Integer.toString(ch, 16);
retval.append("\\u" + s.substring(s.length() - 4));
} else {
retval.appendCodePoint(ch);
}
continue;
}
}
return retval.toString();
}
}