001: /*
002: * xtc - The eXTensible Compiler
003: * Copyright (C) 2004-2007 Robert Grimm
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * version 2 as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
017: * USA.
018: */
019: package xtc.parser;
020:
021: import java.util.ArrayList;
022: import java.util.List;
023:
024: /**
025: * A character switch terminal. This internal element is used to
026: * improve parser performance in recognizing {@link Terminal
027: * terminals}.
028: *
029: * @author Robert Grimm
030: * @version $Revision: 1.8 $
031: */
032: public class CharSwitch extends CharTerminal implements InternalElement {
033:
034: /** The list of {@link CharCase character cases}. */
035: public List<CharCase> cases;
036:
037: /** The optional default element. */
038: public Element base;
039:
040: /**
041: * Create a new character switch element.
042: *
043: * @param cases The list of cases.
044: */
045: public CharSwitch(List<CharCase> cases) {
046: this (cases, null);
047: }
048:
049: /**
050: * Create a new character switch element.
051: *
052: * @param cases The list of cases.
053: * @param base The default element.
054: */
055: public CharSwitch(List<CharCase> cases, Element base) {
056: this .cases = cases;
057: this .base = base;
058: }
059:
060: /**
061: * Create a new character switch element which includes a case for
062: * the specified character class and corresponding element. If the
063: * class is exclusive, the element of the case is left null and the
064: * base is set to the specified element. Furthermore, the specified
065: * class is modified to be non-exclusive.
066: *
067: * @param klass The character class.
068: * @param element The corresponding element.
069: */
070: public CharSwitch(CharClass klass, Element element) {
071: this (new ArrayList<CharCase>(), null);
072:
073: if (klass.exclusive) {
074: klass.exclusive = false;
075: base = element;
076: cases.add(new CharCase(klass));
077: } else {
078: cases.add(new CharCase(klass, element));
079: }
080: }
081:
082: public Tag tag() {
083: return Tag.CHAR_SWITCH;
084: }
085:
086: /**
087: * Determine whether this character switch has a character case for
088: * the specified character class. The specified character class
089: * must be non-exclusive.
090: *
091: * @param klass The character class.
092: * @return The corresponding character case or <code>null</code> if
093: * this character switch does not have a case for the character
094: * class.
095: */
096: public CharCase hasCase(final CharClass klass) {
097: for (CharCase kase : cases) {
098: if (klass.equals(kase.klass)) {
099: return kase;
100: }
101: }
102: return null;
103: }
104:
105: /**
106: * Determine whether this character switch has a character case that
107: * overlaps the specified character class. The specified character
108: * class must be non-exclusive.
109: *
110: * @see CharClass#overlaps(CharClass)
111: *
112: * @param klass The character class.
113: * @return <code>true</code> if this character switch has an overlapping
114: * character case.
115: */
116: public boolean overlaps(final CharClass klass) {
117: for (CharCase kase : cases) {
118: if (klass.overlaps(kase.klass)) {
119: return true;
120: }
121: }
122: return false;
123: }
124:
125: public int hashCode() {
126: int hash = cases.hashCode();
127:
128: if (null == base) {
129: return hash;
130: } else {
131: return hash * 37 + base.hashCode();
132: }
133: }
134:
135: public boolean equals(Object o) {
136: if (this == o)
137: return true;
138: if (!(o instanceof CharSwitch))
139: return false;
140: CharSwitch other = (CharSwitch) o;
141: if (null == base) {
142: if (base != other.base)
143: return false;
144: } else {
145: if (!base.equals(other.base))
146: return false;
147: }
148: return cases.equals(other.cases);
149: }
150:
151: }
|