/*
* Copyright (C) Chaperon. All rights reserved.
* -------------------------------------------------------------------------
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package net.sourceforge.chaperon.process.extended;
import net.sourceforge.chaperon.model.extended.ExtendedGrammar;
import net.sourceforge.chaperon.model.extended.Pattern;
import net.sourceforge.chaperon.model.extended.PatternSet;
/**
* This class represents a set of items, which means positions of definition, in definition. These
* states were used to decribes states.
*
* @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
* @version CVS $Id: State.java,v 1.1 2004/01/04 16:49:12 benedikta Exp $
*/
public class State
{
public State next = null;
//private Item[] items = new Item[0];
public Item first = null;
private ShiftAction[] shiftActions = new ShiftAction[0];
private GotoAction[] gotoActions = new GotoAction[0];
private LookaheadReduceAction[] lookaheadReduceActions = new LookaheadReduceAction[0];
private ReduceAction[] reduceActions = new ReduceAction[0];
private ExtendedGrammar grammar;
public State(ExtendedGrammar grammar)
{
this.grammar = grammar;
}
public boolean addItem(Item newItem)
{
if (first==null)
{
first = newItem;
return true;
}
for (Item item = first; item!=null; item = item.next)
{
if (item.equals(newItem))
return false;
if (item.next==null)
{
item.next = newItem;
return true;
}
}
return true;
}
public boolean isEmpty()
{
return first==null;
}
/**
* Compares two states.
*
* @param o Other state.
*
* @return True, if the states are equal.
*/
public boolean equals(Object o)
{
if (o instanceof State)
{
State state = (State)o;
for (Item item = first; item!=null; item = item.next)
for (Item foreignItem = state.first; foreignItem!=null; foreignItem = foreignItem.next)
{
if (item.equals(foreignItem))
break;
if (foreignItem.next==null)
return false;
}
for (Item foreignItem = state.first; foreignItem!=null; foreignItem = foreignItem.next)
for (Item item = first; item!=null; item = item.next)
{
if (item.equals(foreignItem))
break;
if (item.next==null)
return false;
}
return true;
}
return false;
}
public PatternSet getNextPattern()
{
PatternSet pattern = new PatternSet();
for (Item item = first; item!=null; item = item.next)
if (item.position==Item.SHIFT)
pattern.addPattern(item.pattern);
return pattern;
}
public PatternSet getPreviousPattern()
{
PatternSet pattern = new PatternSet();
for (Item item = first; item!=null; item = item.next)
if ((item.position==Item.GOTO) && (item.pattern!=null))
pattern.addPattern(item.pattern);
return pattern;
}
/**
* Add a transition to this state.
*
* @param symbol Symbol, which forces a transition into another state.
* @param state Destination state.
*/
public boolean addShiftAction(char minimum, char maximum, State state)
{
return addShiftAction(new ShiftAction(minimum, maximum, state));
}
public boolean addShiftAction(ShiftAction action)
{
for (int i = 0; i<shiftActions.length; i++)
{
if (shiftActions[i].equals(action))
if (shiftActions[i].state!=action.state)
throw new IllegalArgumentException("Already shift transition defined with different destination");
else
return false;
// merging actions
if ((shiftActions[i].minimum==(action.maximum+1)) && (shiftActions[i].state==action.state))
{
shiftActions[i] = new ShiftAction(action.minimum, shiftActions[i].maximum, action.state);
return true;
}
if ((shiftActions[i].maximum==(action.minimum-1)) && (shiftActions[i].state==action.state))
{
shiftActions[i] = new ShiftAction(shiftActions[i].minimum, action.maximum, action.state);
return true;
}
}
ShiftAction[] newShiftActions = new ShiftAction[shiftActions.length+1];
System.arraycopy(shiftActions, 0, newShiftActions, 0, shiftActions.length);
newShiftActions[shiftActions.length] = action;
shiftActions = newShiftActions;
return true;
}
public ShiftAction[] getShiftActions()
{
return shiftActions;
}
public ShiftAction getShiftAction(char character)
{
for (int i = 0; i<shiftActions.length; i++)
if ((shiftActions[i].minimum<=character) && (shiftActions[i].maximum>=character))
return shiftActions[i];
return null;
}
public void addGotoAction(String symbol, State state)
{
addGotoAction(new GotoAction(symbol, state));
}
public void addGotoAction(Pattern pattern, State state)
{
addGotoAction(new GotoAction(pattern, state));
}
public void addGotoAction(GotoAction action)
{
for (int i = 0; i<gotoActions.length; i++)
if (gotoActions[i].equals(action))
if (gotoActions[i].state!=action.state)
throw new IllegalArgumentException("Already goto transition defined with different destination");
else
return;
GotoAction[] newGotoActions = new GotoAction[gotoActions.length+1];
for (int i = 0; i<gotoActions.length; i++)
newGotoActions[i] = gotoActions[i];
newGotoActions[gotoActions.length] = action;
gotoActions = newGotoActions;
}
public GotoAction[] getGotoActions()
{
return gotoActions;
}
public GotoAction getGotoAction(String symbol)
{
for (int i = 0; i<gotoActions.length; i++)
if ((gotoActions[i].symbol!=null) && (gotoActions[i].symbol.equals(symbol)))
return gotoActions[i];
return null;
}
public GotoAction getGotoAction(Pattern pattern)
{
for (int i = 0; i<gotoActions.length; i++)
if (gotoActions[i].pattern==pattern)
return gotoActions[i];
return null;
}
public GotoAction getGotoAction(ReduceAction action)
{
if (action.symbol!=null)
{
for (int i = 0; i<gotoActions.length; i++)
if ((gotoActions[i].symbol!=null) && (gotoActions[i].symbol.equals(action.symbol)))
return gotoActions[i];
}
else
{
for (int i = 0; i<gotoActions.length; i++)
if (gotoActions[i].pattern==action.pattern)
return gotoActions[i];
}
return null;
}
public void addLookaheadReduceAction(char minimum, char maximum, String symbol, int length)
{
addLookaheadReduceAction(new LookaheadReduceAction(minimum, maximum, symbol, length));
}
public void addLookaheadReduceAction(char minimum, char maximum, Pattern pattern, int length)
{
addLookaheadReduceAction(new LookaheadReduceAction(minimum, maximum, pattern, length));
}
public boolean addLookaheadReduceAction(LookaheadReduceAction action)
{
for (int i = 0; i<lookaheadReduceActions.length; i++)
{
if (lookaheadReduceActions[i].equals(action))
return false;
// merging actions
if (lookaheadReduceActions[i].symbol!=null)
{
if ((lookaheadReduceActions[i].minimum==(action.maximum+1)) &&
(lookaheadReduceActions[i].symbol.equals(action.symbol)) &&
(lookaheadReduceActions[i].length==action.length))
{
lookaheadReduceActions[i] =
new LookaheadReduceAction(action.minimum, lookaheadReduceActions[i].maximum,
action.symbol, action.length);
return true;
}
if ((lookaheadReduceActions[i].maximum==(action.minimum-1)) &&
(lookaheadReduceActions[i].symbol.equals(action.symbol)) &&
(lookaheadReduceActions[i].length==action.length))
{
lookaheadReduceActions[i] =
new LookaheadReduceAction(lookaheadReduceActions[i].minimum, action.maximum,
action.symbol, action.length);
return true;
}
}
else
{
if ((lookaheadReduceActions[i].minimum==(action.maximum+1)) &&
(lookaheadReduceActions[i].pattern==action.pattern) &&
(lookaheadReduceActions[i].length==action.length))
{
lookaheadReduceActions[i] =
new LookaheadReduceAction(action.minimum, lookaheadReduceActions[i].maximum,
action.pattern, action.length);
return true;
}
if ((lookaheadReduceActions[i].maximum==(action.minimum-1)) &&
(lookaheadReduceActions[i].pattern==action.pattern) &&
(lookaheadReduceActions[i].length==action.length))
{
lookaheadReduceActions[i] =
new LookaheadReduceAction(lookaheadReduceActions[i].minimum, action.maximum,
action.pattern, action.length);
return true;
}
}
}
LookaheadReduceAction[] newLookaheadReduceActions =
new LookaheadReduceAction[lookaheadReduceActions.length+1];
for (int i = 0; i<lookaheadReduceActions.length; i++)
newLookaheadReduceActions[i] = lookaheadReduceActions[i];
newLookaheadReduceActions[lookaheadReduceActions.length] = action;
lookaheadReduceActions = newLookaheadReduceActions;
return true;
}
public LookaheadReduceAction[] getLookaheadReduceActions()
{
return lookaheadReduceActions;
}
public void addReduceAction(String symbol, int length)
{
addReduceAction(new ReduceAction(symbol, length));
}
public void addReduceAction(Pattern pattern, int length)
{
addReduceAction(new ReduceAction(pattern, length));
}
public void addReduceAction(ReduceAction action)
{
for (int i = 0; i<reduceActions.length; i++)
if (reduceActions[i].equals(action))
return;
ReduceAction[] newReduceActions = new ReduceAction[reduceActions.length+1];
for (int i = 0; i<reduceActions.length; i++)
newReduceActions[i] = reduceActions[i];
newReduceActions[reduceActions.length] = action;
reduceActions = newReduceActions;
}
public ReduceAction[] getReduceActions()
{
return reduceActions;
}
/**
* Return a string representation of this state.
*
* @return String representation of this state.
*/
public String toString()
{
StringBuffer buffer = new StringBuffer();
for (Item item = first; item!=null; item = item.next)
{
buffer.append(item);
buffer.append("\n");
}
return buffer.toString();
}
}