package de.unisiegen.gtitool.core.entities.regex;
import java.util.ArrayList;
import javax.swing.event.EventListenerList;
import de.unisiegen.gtitool.core.entities.DefaultSymbol;
import de.unisiegen.gtitool.core.entities.Entity;
import de.unisiegen.gtitool.core.entities.Symbol;
import de.unisiegen.gtitool.core.entities.listener.PrettyStringChangedListener;
import de.unisiegen.gtitool.core.parser.ParserOffset;
import de.unisiegen.gtitool.core.parser.style.PrettyPrintable;
import de.unisiegen.gtitool.core.parser.style.PrettyString;
import de.unisiegen.gtitool.core.parser.style.PrettyToken;
import de.unisiegen.gtitool.core.parser.style.Style;
/**
* @author Simon Meurer
* @version
*/
public class CharacterClassNode extends LeafNode
{
/**
* The serial version uid
*/
private static final long serialVersionUID = -700140811311936745L;
/**
* The flag that indicates if the Character class is represented as an array
*/
private boolean array;
/**
* The first char of the character class
*/
private char char1;
/**
* The last char of the character class
*/
private char char2;
/**
* The chars of the character class as an array
*/
private char [] chars;
/**
* The {@link EventListenerList}.
*/
private EventListenerList listenerList = new EventListenerList ();
/**
* The offset of this {@link CharacterClassNode} in the source code.
*/
private ParserOffset parserOffset = NO_PARSER_OFFSET;
/**
* The position in the Syntaxtree
*/
private int position;
/**
* Constructor for a {@link CharacterClassNode} represented as an array
*
* @param chars The array representing the chars of the CharacterClass
*/
public CharacterClassNode ( char ... chars )
{
this.array = true;
this.chars = chars;
}
/**
* Constructor for a {@link CharacterClassNode} represented with first and
* last char
*
* @param char1 First char of the CharacterClass
* @param char2 Last char of the CharacterClass
*/
public CharacterClassNode ( char char1, char char2 )
{
this.array = false;
this.char1 = char1;
this.char2 = char2;
}
/**
* {@inheritDoc}
*
* @see PrettyPrintable#addPrettyStringChangedListener(de.unisiegen.gtitool.core.entities.listener.PrettyStringChangedListener)
*/
public void addPrettyStringChangedListener (
PrettyStringChangedListener listener )
{
this.listenerList.add ( PrettyStringChangedListener.class, listener );
}
/**
* {@inheritDoc}
*
* @see de.unisiegen.gtitool.core.entities.regex.RegexNode#clone()
*/
@Override
public RegexNode clone ()
{
if ( this.array )
{
return new CharacterClassNode ( this.chars );
}
return new CharacterClassNode ( this.char1, this.char2 );
}
/**
* {@inheritDoc}
*
* @see Comparable#compareTo(Object)
*/
public int compareTo ( RegexNode arg0 )
{
if ( arg0 instanceof LeafNode )
{
LeafNode leaf = ( LeafNode ) arg0;
return this.position - leaf.getPosition ();
}
return -1;
}
/**
* {@inheritDoc}
*
* @see Object#equals(java.lang.Object)
*/
@Override
public boolean equals ( Object obj )
{
if ( obj == this )
{
return true;
}
if ( obj instanceof CharacterClassNode )
{
CharacterClassNode charNode = ( CharacterClassNode ) obj;
if ( ( this.char1 == charNode.char1 ) && ( this.char2 == charNode.char2 ) )
{
return this.position == ( ( CharacterClassNode ) obj ).position;
}
}
return false;
}
/**
* {@inheritDoc} RegexNode#getAllChildren()
*/
@Override
public ArrayList < RegexNode > getAllChildren ()
{
ArrayList < RegexNode > nodes = new ArrayList < RegexNode > ();
return nodes;
}
/**
* Returns the Characters in the Character Class as {@link Symbol}s
*
* @return The Characters in the Character Class as Symbols
*/
public ArrayList < Symbol > getCharacters ()
{
ArrayList < Symbol > symbols = new ArrayList < Symbol > ();
if ( this.array )
{
for ( char c : this.chars )
{
symbols.add ( new DefaultSymbol ( Character.toString ( c ) ) );
}
}
else
{
char c1 = this.char1;
char c2 = this.char2;
while ( c1 <= c2 )
{
symbols.add ( new DefaultSymbol ( Character.toString ( c1++ ) ) );
}
}
return symbols;
}
/**
* {@inheritDoc}
*
* @see RegexNode#getChildren()
*/
@Override
public ArrayList < RegexNode > getChildren ()
{
return new ArrayList < RegexNode > ();
}
/**
* {@inheritDoc}
*
* @see RegexNode#getLeftChildrenCount()
*/
@Override
public int getLeftChildrenCount ()
{
return 0;
}
/**
* {@inheritDoc}
*
* @see RegexNode#getNextUnfinishedNode()
*/
@Override
public UnfinishedNode getNextUnfinishedNode ()
{
return null;
}
/**
* {@inheritDoc}
*
* @see RegexNode#getNodeString()
*/
@Override
public PrettyString getNodeString ()
{
if ( !this.array )
{
PrettyString string = new PrettyString ();
string.add ( new PrettyToken ( "[", Style.SYMBOL ) ); //$NON-NLS-1$
string.add ( new PrettyToken ( Character.toString ( this.char1 ),
Style.TOKEN ) );
string.add ( new PrettyToken ( "-", Style.SYMBOL ) ); //$NON-NLS-1$
string.add ( new PrettyToken ( Character.toString ( this.char2 ),
Style.TOKEN ) );
string.add ( new PrettyToken ( "]", Style.SYMBOL ) ); //$NON-NLS-1$
return string;
}
PrettyString string = new PrettyString ();
string.add ( new PrettyToken ( "[", Style.SYMBOL ) ); //$NON-NLS-1$
for ( char c : this.chars )
{
string.add ( new PrettyToken ( Character.toString ( c ), Style.TOKEN ) );
}
string.add ( new PrettyToken ( "]", Style.SYMBOL ) ); //$NON-NLS-1$
return string;
}
/**
* {@inheritDoc}
*
* @see Entity#getParserOffset()
*/
public ParserOffset getParserOffset ()
{
return this.parserOffset;
}
/**
* {@inheritDoc}
*
* @see LeafNode#getPosition()
*/
@Override
public int getPosition ()
{
return this.position;
}
/**
* {@inheritDoc}
*
* @see RegexNode#getRightChildrenCount()
*/
@Override
public int getRightChildrenCount ()
{
return 0;
}
/**
* {@inheritDoc}
*
* @see RegexNode#isInCoreSyntax()
*/
@Override
public boolean isInCoreSyntax ()
{
return false;
}
/**
* {@inheritDoc}
*
* @see RegexNode#nullable()
*/
@Override
public boolean nullable ()
{
return false;
}
/**
* {@inheritDoc}
*
* @see PrettyPrintable#removePrettyStringChangedListener(de.unisiegen.gtitool.core.entities.listener.PrettyStringChangedListener)
*/
public void removePrettyStringChangedListener (
PrettyStringChangedListener listener )
{
this.listenerList.remove ( PrettyStringChangedListener.class, listener );
}
/**
* {@inheritDoc}
*
* @see Entity#setParserOffset(ParserOffset)
*/
public void setParserOffset ( ParserOffset parserOffset )
{
this.parserOffset = parserOffset;
}
/**
* {@inheritDoc}
*
* @see LeafNode#getPosition()
*/
@Override
public void setPosition ( int position )
{
this.position = position;
}
/**
* {@inheritDoc}
*
* @see RegexNode#toCoreSyntax(boolean)
*/
@Override
public RegexNode toCoreSyntax ( boolean withCharacterClasses )
{
if ( withCharacterClasses )
{
if ( !this.array )
{
if ( this.char1 < this.char2 - 1 )
{
DisjunctionNode dis = new DisjunctionNode ( ( new CharacterClassNode (
this.char1, ( char ) ( this.char2 - 1 ) )
.toCoreSyntax ( withCharacterClasses ) ), new TokenNode (
Character.toString ( this.char2 ) ) );
return dis;
}
DisjunctionNode dis = new DisjunctionNode ( new TokenNode ( Character
.toString ( this.char1 ) ), new TokenNode ( Character
.toString ( this.char2 ) ) );
return dis;
}
if ( this.chars.length > 2 )
{
char [] newChars = new char [ this.chars.length - 1 ];
System.arraycopy ( this.chars, 0, newChars, 0, this.chars.length - 1 );
DisjunctionNode dis = new DisjunctionNode ( new CharacterClassNode (
newChars ).toCoreSyntax ( withCharacterClasses ), new TokenNode (
Character.toString ( this.chars [ this.chars.length - 1 ] ) ) );
return dis;
}
DisjunctionNode dis = new DisjunctionNode ( new TokenNode ( Character
.toString ( this.chars [ 0 ] ) ), new TokenNode ( Character
.toString ( this.chars [ 1 ] ) ) );
return dis;
}
return this;
}
/**
* {@inheritDoc}
*
* @see PrettyPrintable#toPrettyString()
*/
public PrettyString toPrettyString ()
{
PrettyString string = new PrettyString ();
if ( !this.array )
{
string.add ( new PrettyToken ( "[", Style.SYMBOL ) ); //$NON-NLS-1$
string.add ( new PrettyToken ( Character.toString ( this.char1 ),
Style.TOKEN ) );
string.add ( new PrettyToken ( "-", Style.SYMBOL ) ); //$NON-NLS-1$
string.add ( new PrettyToken ( Character.toString ( this.char2 ),
Style.TOKEN ) );
string.add ( new PrettyToken ( "]", Style.SYMBOL ) ); //$NON-NLS-1$
return string;
}
string.add ( new PrettyToken ( "[", Style.SYMBOL ) ); //$NON-NLS-1$
for ( char c : this.chars )
{
string.add ( new PrettyToken ( Character.toString ( c ), Style.TOKEN ) );
}
string.add ( new PrettyToken ( "]", Style.SYMBOL ) ); //$NON-NLS-1$
return string;
}
/**
* {@inheritDoc}
*
* @see Object#toString()
*/
@Override
public String toString ()
{
if ( !this.array )
{
return "[" + this.char1 + "-" + this.char2 + "]"; //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
}
String s = "["; //$NON-NLS-1$
for ( char c : this.chars )
{
s += c;
}
s += "]"; //$NON-NLS-1$
return s;
}
}