/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This file is part of SableCC. * * See the file "LICENSE" for copyright information and the * * terms and conditions for copying, distribution and * * modification of SableCC. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ package org.sablecc.sablecc; import java.util.Vector; @SuppressWarnings({"rawtypes", "unchecked"}) final class SymbolSet implements Cloneable { private final IntSet terminals; private final IntSet nonterminals; private boolean empty; private boolean modified = true; private Symbol[] symbols; private void computeArray() { Vector symbols = new Vector(0); int[] elements = terminals.elements(); for (int i = 0; i < elements.length; i++) { symbols.addElement(Symbol.symbol(elements[i], true)); } elements = nonterminals.elements(); for (int i = 0; i < elements.length; i++) { symbols.addElement(Symbol.symbol(elements[i], false)); } this.symbols = new Symbol[symbols.size()]; symbols.copyInto(this.symbols); modified = false; } SymbolSet() { this.terminals = new IntSet(); this.nonterminals = new IntSet(); } private SymbolSet(SymbolSet set ) { this.terminals = (IntSet) set.terminals.clone(); this.nonterminals = (IntSet) set.nonterminals.clone(); this.empty = set.empty; } void setTerminal(int terminal) { terminals.set(terminal); modified = true; } void clearTerminal(int terminal) { terminals.clear(terminal); modified = true; } boolean getTerminal(int terminal) { return terminals.get(terminal); } void setNonterminal(int nonterminal) { nonterminals.set(nonterminal); modified = true; } void clearNonterminal(int nonterminal) { nonterminals.clear(nonterminal); modified = true; } boolean getNonterminal(int nonterminal) { return nonterminals.get(nonterminal); } void setEmpty() { empty = true; modified = true; } void clearEmpty() { empty = false; modified = true; } boolean getEmpty() { return empty; } void and(SymbolSet s) { terminals.and(s.terminals); nonterminals.and(s.nonterminals); empty &= s.empty; modified = true; } void or(SymbolSet s) { terminals.or(s.terminals); nonterminals.or(s.nonterminals); empty |= s.empty; modified = true; } void xor(SymbolSet s) { terminals.xor(s.terminals); nonterminals.xor(s.nonterminals); empty ^= s.empty; modified = true; } @Override public int hashCode() { return terminals.hashCode() + nonterminals.hashCode() + new Boolean(empty).hashCode(); } @Override public boolean equals(Object obj) { if ((obj == null) || (obj.getClass() != this.getClass())) { return false; } SymbolSet s = (SymbolSet) obj; return terminals.equals(s.terminals) && nonterminals.equals(s.nonterminals) && (empty == s.empty); } Symbol[] getSymbols() { if (modified) { computeArray(); } return symbols; } @Override public String toString() { StringBuffer result = new StringBuffer(); result.append("{"); Symbol[] symbols = getSymbols(); boolean comma = false; for (int i = 0; i < symbols.length; i++) { if (comma) { result.append(","); } else { comma = true; } result.append(symbols[i]); } if (empty) { if (comma) { result.append(","); } else { comma = true; } result.append("*empty*"); } result.append("}"); return result.toString(); } @Override public Object clone() { return new SymbolSet(this); } }