001    package toolbus.process;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    import java.util.Stack;
006    import toolbus.AtomList;
007    import toolbus.State;
008    import toolbus.StateElement;
009    import toolbus.TBTermFactory;
010    import toolbus.environment.Environment;
011    import toolbus.exceptions.ToolBusException;
012    import toolbus.parsercup.PositionInformation;
013    import toolbus.process.debug.ExecutionResult;
014    import aterm.ATerm;
015    
016    /**
017     * LeftBiasedAlternative implements the the asymmetric choice operator operator <+. It is similar
018     * to + but prefers its left argument.
019     * 
020     * @author Arnold Lankamp
021     */
022    public class LeftBiasedAlternative extends ProcessExpression implements StateElement{
023            private final int LEFT = 0;
024            private final int RIGHT = 1;
025            
026            private ProcessInstance processInstance;
027            
028            private final ProcessExpression[] expr;
029            
030            private final State[] state;
031            private final State mergeState;
032            
033            private boolean leftLast = false;
034            
035            public LeftBiasedAlternative(ProcessExpression left, ProcessExpression right, TBTermFactory tbfactory, PositionInformation posInfo){
036                    super(tbfactory, posInfo);
037                    
038                    expr = new ProcessExpression[2];
039                    expr[LEFT] = left;
040                    expr[RIGHT] = right;
041                    
042                    state = new State[2];
043                    mergeState = new State();
044                    mergeState.addElement(this);
045            }
046            
047            protected void computeFirst(){
048                    expr[LEFT].computeFirst();
049                    expr[RIGHT].computeFirst();
050            }
051            
052            protected void compile(ProcessInstance processInstance, Stack<String> calls, State follows) throws ToolBusException{
053                    this.processInstance = processInstance;
054                    
055                    expr[LEFT].compile(processInstance, calls, follows);
056                    state[LEFT] = expr[LEFT].getFirst();
057                    
058                    expr[RIGHT].compile(processInstance, calls, follows);
059                    state[RIGHT] = expr[RIGHT].getFirst();
060                    setFollow(follows);
061            }
062            
063            protected void replaceFormals(Environment env) throws ToolBusException{
064                    expr[LEFT].replaceFormals(env);
065                    expr[RIGHT].replaceFormals(env);
066            }
067            
068            protected ProcessExpression copy(){
069                    return new LeftBiasedAlternative(expr[LEFT].copy(), expr[RIGHT].copy(), tbfactory, getPosInfo());
070            }
071            
072            public AtomList getAtoms(){
073                    return expr[LEFT].getAtoms().union(expr[RIGHT].getAtoms());
074            }
075            
076            public State getFirst(){
077                    return mergeState;
078            }
079            
080            public boolean contains(StateElement a){
081                    return state[LEFT].contains(a) || state[RIGHT].contains(a);
082            }
083            
084            public ProcessInstance getProcess(){
085                    return processInstance;
086            }
087            
088            public void setTest(ATerm test, Environment env) throws ToolBusException{
089                    state[LEFT].setTest(test, env);
090                    state[RIGHT].setTest(test, env);
091            }
092            
093            public List<ATerm> getTests(){
094                    return new ArrayList<ATerm>(0);
095            }
096            
097            public boolean isEnabled(){
098                    return state[LEFT].isEnabled() || state[RIGHT].isEnabled();
099            }
100            
101            public State gotoNextStateAndActivate(){
102                    if(leftLast) return state[LEFT].gotoNextStateAndActivate();
103                    
104                    return state[RIGHT].gotoNextStateAndActivate();
105            }
106            
107            public State gotoNextStateAndActivate(StateElement se){
108                    if(state[LEFT].contains(se)) return state[LEFT].gotoNextStateAndActivate(se);
109                            
110                    return state[RIGHT].gotoNextStateAndActivate(se);
111            }
112            
113            public void activate(){
114                    state[LEFT].activate();
115                    state[RIGHT].activate();
116            }
117            
118            public boolean execute() throws ToolBusException{
119                    if(state[LEFT].execute()){
120                            leftLast = true;
121                            return true;
122                    }else if(state[RIGHT].execute()){
123                            leftLast = false;
124                            return true;
125                    }else return false;
126            }
127            
128            public ProcessInstance[] debugExecute() throws ToolBusException{
129                    ExecutionResult er;
130                    if((er = state[LEFT].debugExecute()) != null){
131                            leftLast = true;
132                            return er.partners;
133                    }else if((er = state[RIGHT].debugExecute()) != null){
134                            leftLast = false;
135                            return er.partners;
136                    }
137                    
138                    return null;
139            }
140            
141            public String toString(){
142                    return "LeftBiasedAlternative(" + state[LEFT] + "; " + state[RIGHT] + ")";
143            }
144    }