/*******************************************************************************
* Copyright (c) 2008 Scott Stanchfield.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Based on the ANTLR parser generator by Terence Parr, http://antlr.org
* Ric Klaren <klaren@cs.utwente.nl>
* Scott Stanchfield - Modifications for XML Parsing
*******************************************************************************/
package com.javadude.antxr;
import com.javadude.antxr.collections.AST;
import com.javadude.antxr.collections.impl.BitSet;
public class MismatchedTokenException extends RecognitionException {
private static final long serialVersionUID = 1L;
// Token names array for formatting
String[] tokenNames;
// The token that was encountered
public Token token;
// The offending AST node if tree walking
public AST node;
String tokenText = null; // taken from node or token object
// Types of tokens
public static final int TOKEN = 1;
public static final int NOT_TOKEN = 2;
public static final int RANGE = 3;
public static final int NOT_RANGE = 4;
public static final int SET = 5;
public static final int NOT_SET = 6;
// One of the above
public int mismatchType;
// For TOKEN/NOT_TOKEN and RANGE/NOT_RANGE
public int expecting;
// For RANGE/NOT_RANGE (expecting is lower bound of range)
public int upper;
// For SET/NOT_SET
public BitSet set;
/** Looking for AST wildcard, didn't find it */
public MismatchedTokenException() {
super("Mismatched Token: expecting any AST node", "<AST>", -1, -1);
}
// Expected range / not range
public MismatchedTokenException(String[] tokenNames_, AST node_, int lower, int upper_, boolean matchNot) {
super("Mismatched Token", "<AST>", node_==null? -1:node_.getLine(), node_==null? -1:node_.getColumn());
tokenNames = tokenNames_;
node = node_;
if (node_ == null) {
tokenText = "<empty tree>";
}
else {
tokenText = node_.toString();
}
mismatchType = matchNot ? MismatchedTokenException.NOT_RANGE : MismatchedTokenException.RANGE;
expecting = lower;
upper = upper_;
}
// Expected token / not token
public MismatchedTokenException(String[] tokenNames_, AST node_, int expecting_, boolean matchNot) {
super("Mismatched Token", "<AST>", node_==null? -1:node_.getLine(), node_==null? -1:node_.getColumn());
tokenNames = tokenNames_;
node = node_;
if (node_ == null) {
tokenText = "<empty tree>";
}
else {
tokenText = node_.toString();
}
mismatchType = matchNot ? MismatchedTokenException.NOT_TOKEN : MismatchedTokenException.TOKEN;
expecting = expecting_;
}
// Expected BitSet / not BitSet
public MismatchedTokenException(String[] tokenNames_, AST node_, BitSet set_, boolean matchNot) {
super("Mismatched Token", "<AST>", node_==null? -1:node_.getLine(), node_==null? -1:node_.getColumn());
tokenNames = tokenNames_;
node = node_;
if (node_ == null) {
tokenText = "<empty tree>";
}
else {
tokenText = node_.toString();
}
mismatchType = matchNot ? MismatchedTokenException.NOT_SET : MismatchedTokenException.SET;
set = set_;
}
// Expected range / not range
public MismatchedTokenException(String[] tokenNames_, Token token_, int lower, int upper_, boolean matchNot, String fileName_) {
super("Mismatched Token", fileName_, token_.getLine(), token_.getColumn());
tokenNames = tokenNames_;
token = token_;
tokenText = token_.getText();
mismatchType = matchNot ? MismatchedTokenException.NOT_RANGE : MismatchedTokenException.RANGE;
expecting = lower;
upper = upper_;
}
// Expected token / not token
public MismatchedTokenException(String[] tokenNames_, Token token_, int expecting_, boolean matchNot, String fileName_) {
super("Mismatched Token", fileName_, token_.getLine(), token_.getColumn());
tokenNames = tokenNames_;
token = token_;
tokenText = token_.getText();
mismatchType = matchNot ? MismatchedTokenException.NOT_TOKEN : MismatchedTokenException.TOKEN;
expecting = expecting_;
}
// Expected BitSet / not BitSet
public MismatchedTokenException(String[] tokenNames_, Token token_, BitSet set_, boolean matchNot, String fileName_) {
super("Mismatched Token", fileName_, token_.getLine(), token_.getColumn());
tokenNames = tokenNames_;
token = token_;
tokenText = token_.getText();
mismatchType = matchNot ? MismatchedTokenException.NOT_SET : MismatchedTokenException.SET;
set = set_;
}
/**
* Returns a clean error message (no line number/column information)
*/
@Override
public String getMessage() {
StringBuffer sb = new StringBuffer();
switch (mismatchType) {
case TOKEN:
sb.append("expecting " + tokenName(expecting) + ", found '" + tokenText + "'");
break;
case NOT_TOKEN:
sb.append("expecting anything but " + tokenName(expecting) + "; got it anyway");
break;
case RANGE:
sb.append("expecting token in range: " + tokenName(expecting) + ".." + tokenName(upper) + ", found '" + tokenText + "'");
break;
case NOT_RANGE:
sb.append("expecting token NOT in range: " + tokenName(expecting) + ".." + tokenName(upper) + ", found '" + tokenText + "'");
break;
case SET:
case NOT_SET:
sb.append("expecting " + (mismatchType == MismatchedTokenException.NOT_SET ? "NOT " : "") + "one of (");
int[] elems = set.toArray();
for (int i = 0; i < elems.length; i++) {
sb.append(" ");
sb.append(tokenName(elems[i]));
}
sb.append("), found '" + tokenText + "'");
break;
default :
sb.append(super.getMessage());
break;
}
return sb.toString();
}
private String tokenName(int tokenType) {
if (tokenType == Token.INVALID_TYPE) {
return "<Set of tokens>";
}
else if (tokenType < 0 || tokenType >= tokenNames.length) {
return "<" + String.valueOf(tokenType) + ">";
}
else {
return tokenNames[tokenType];
}
}
}