/*
* xtc - The eXTensible Compiler
* Copyright (C) 2004-2007 Robert Grimm
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package xtc.parser;
import java.util.ArrayList;
import java.util.List;
/**
* A character switch terminal. This internal element is used to
* improve parser performance in recognizing {@link Terminal
* terminals}.
*
* @author Robert Grimm
* @version $Revision: 1.8 $
*/
public class CharSwitch extends CharTerminal implements InternalElement {
/** The list of {@link CharCase character cases}. */
public List<CharCase> cases;
/** The optional default element. */
public Element base;
/**
* Create a new character switch element.
*
* @param cases The list of cases.
*/
public CharSwitch(List<CharCase> cases) {
this(cases, null);
}
/**
* Create a new character switch element.
*
* @param cases The list of cases.
* @param base The default element.
*/
public CharSwitch(List<CharCase> cases, Element base) {
this.cases = cases;
this.base = base;
}
/**
* Create a new character switch element which includes a case for
* the specified character class and corresponding element. If the
* class is exclusive, the element of the case is left null and the
* base is set to the specified element. Furthermore, the specified
* class is modified to be non-exclusive.
*
* @param klass The character class.
* @param element The corresponding element.
*/
public CharSwitch(CharClass klass, Element element) {
this(new ArrayList<CharCase>(), null);
if (klass.exclusive) {
klass.exclusive = false;
base = element;
cases.add(new CharCase(klass));
} else {
cases.add(new CharCase(klass, element));
}
}
public Tag tag() {
return Tag.CHAR_SWITCH;
}
/**
* Determine whether this character switch has a character case for
* the specified character class. The specified character class
* must be non-exclusive.
*
* @param klass The character class.
* @return The corresponding character case or <code>null</code> if
* this character switch does not have a case for the character
* class.
*/
public CharCase hasCase(final CharClass klass) {
for (CharCase kase : cases) {
if (klass.equals(kase.klass)) {
return kase;
}
}
return null;
}
/**
* Determine whether this character switch has a character case that
* overlaps the specified character class. The specified character
* class must be non-exclusive.
*
* @see CharClass#overlaps(CharClass)
*
* @param klass The character class.
* @return <code>true</code> if this character switch has an overlapping
* character case.
*/
public boolean overlaps(final CharClass klass) {
for (CharCase kase : cases) {
if (klass.overlaps(kase.klass)) {
return true;
}
}
return false;
}
public int hashCode() {
int hash = cases.hashCode();
if (null == base) {
return hash;
} else {
return hash * 37 + base.hashCode();
}
}
public boolean equals(Object o) {
if (this == o) return true;
if (! (o instanceof CharSwitch)) return false;
CharSwitch other = (CharSwitch)o;
if (null == base) {
if (base != other.base) return false;
} else {
if (! base.equals(other.base)) return false;
}
return cases.equals(other.cases);
}
}