ScannerUtil.java
package org.sterling.source.scanner;
import static java.lang.Character.isISOControl;
import static java.lang.Character.isWhitespace;
import static java.util.Arrays.asList;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import org.sterling.SterlingException;
import org.sterling.source.exception.InvalidEscapeSequenceException;
import org.sterling.source.exception.ScannerException;
import org.sterling.source.exception.UnterminatedCharacterException;
import org.sterling.source.exception.UnterminatedStringException;
import org.sterling.source.syntax.NodeKind;
public final class ScannerUtil {
public static SterlingException invalidEscapeSequence(InputReader reader, NodeKind kind) {
return new InvalidEscapeSequenceException("Invalid escape sequence in " + kind + " [" + reader.getLocation() + "]");
}
public static SterlingException unexpectedInput(InputReader reader, Collection<NodeKind> expectedKinds) {
while (!reader.expect('\0') && !reader.expect('\n') && isWhitespace(reader.peek())) {
reader.skip();
}
ScannerException exception = new ScannerException("Unexpected " + getName(reader)
+ " '" + getValue(reader) + "', expecting " + listKinds(expectedKinds)
+ " [" + reader.getLocation() + "]");
reader.reject();
return exception;
}
public static SterlingException unexpectedInput(InputReader reader, NodeKind... expectedKinds) {
return unexpectedInput(reader, asList(expectedKinds));
}
public static SterlingException unterminatedCharacter(InputReader reader, NodeKind kind) {
return new UnterminatedCharacterException("Unterminated " + kind + " [" + reader.getLocation() + "]");
}
public static SterlingException unterminatedString(InputReader reader, NodeKind kind) {
return new UnterminatedStringException("Unterminated " + kind + " [" + reader.getLocation() + "]");
}
private static String getName(InputReader reader) {
char value = reader.peek();
return (value == '\0') ? "END OF INPUT" : Character.getName(value);
}
private static String getValue(InputReader reader) {
char value = reader.peek();
if (' ' != value && (isWhitespace(value) || isISOControl(value))) {
return "";
} else {
return String.valueOf(value);
}
}
private static String listKinds(Collection<NodeKind> kinds) {
StringBuilder builder = new StringBuilder();
Deque<NodeKind> queue = new ArrayDeque<>(kinds);
builder.append(queue.pop());
while (queue.size() > 1) {
builder.append(", ");
builder.append(queue.pop());
}
if (queue.size() > 0) {
builder.append(" or ");
builder.append(queue.pop());
}
return builder.toString();
}
private ScannerUtil() {
// intentionally empty
}
}