/// <summary> /// Sets conditioned actions to current state. /// </summary> /// <param name="currentState">The state which actions will be set.</param> /// <param name="targetState">The target state of actions.</param> /// <param name="actions">The actions to be set.</param> /// <param name="defaultActionState">If available it is a default state used when conditions won't match.</param> private void setConditionedActions(AutomatonState currentState, AutomatonState targetState, Dictionary<string, AutomatonBuilderDirector> actions, AutomatonState defaultActionState) { foreach (var actionPair in actions) { var actionState = getActionState(currentState, actionPair.Key, defaultActionState); actionState.SetAction(actionPair.Value, targetState); } }
internal AutomatonBuilder() { _context = new AutomatonBuilderContext(); _rootState = _context.CreateNewState(); _lastTargetState = _rootState; }
/// <summary> /// Finds/creates a state representing condition occurence on startState. /// </summary> /// <param name="startState">State from which condition is tested.</param> /// <param name="condition">Tested condition.</param> /// <returns>The conditioned state.</returns> private AutomatonState getActionState(AutomatonState startState, string condition, AutomatonState defaultActionState = null) { var currentState = startState; for (var i = 0; i < condition.Length; ++i) { //find/create state path corresponding with the condition var ch = condition[i]; var byteLower = (byte)char.ToLower(ch); var byteUpper = (byte)char.ToUpper(ch); if (!currentState.HasByteTarget(byteLower)) { var nextState = _context.CreateNewState(); currentState.SetByteTarget(byteLower, nextState); currentState.SetByteTarget(byteUpper, nextState); } currentState.SetDefaultByteTarget(defaultActionState); currentState = currentState.GetByteTarget(byteLower); } return currentState; }
/// <summary> /// Prepares new state for emission and target state. /// </summary> /// <param name="currentState">State prepared for emission.</param> /// <param name="targetState">State that will be used as a target when emitted action is completed.</param> private void prepareNewState(out AutomatonState currentState, out AutomatonState targetState) { //we will begin with state that was used as last target. currentState = _lastTargetState; //pre-create next state as a target if (_repeatedTargetState == null) { targetState = _context.CreateNewState(); _lastTargetState = targetState; } else { //target is repeated targetState = _lastTargetState; } }
internal void SetDefaultByteTarget(AutomatonState defaultByteTarget) { if (_defaultByteTarget != null && _defaultByteTarget != defaultByteTarget) throw new NotSupportedException("Cannot override default byte target"); _defaultByteTarget = defaultByteTarget; }
/// <summary> /// Emits directed actions conditioned by indexing strings repeating until empty line. /// </summary> /// <param name="actions">Actions to emit.</param> internal void Emit_RepeatedActionSwitch(Dictionary<string, AutomatonBuilderDirector> actions, AutomatonBuilderDirector defaultConditionAction = null) { //set repeating of target state _repeatedTargetState = _lastTargetState; AutomatonState currentState; AutomatonState targetState; prepareNewState(out currentState, out targetState); AutomatonState defaultConditionState = null; if (defaultConditionAction != null) { defaultConditionState = _context.CreateNewState(); defaultConditionState.SetAction(defaultConditionAction, targetState); } //setting current state as output state will cause repeating of the state. setConditionedActions(currentState, currentState, actions, defaultConditionState); }
/// <summary> /// Sets target for given byte input. /// </summary> /// <param name="b">Condition byte.</param> /// <param name="target">Target state.</param> internal void SetByteTarget(byte b, AutomatonState target) { if (_director != null) throw new NotImplementedException("cannot set byte target when state action is present"); if (_byteTargets.ContainsKey(b) && _byteTargets[b] == target) //target is already set return; _byteTargets.Add(b, target); }
/// <summary> /// Sets action for current state, ending at target state. /// </summary> /// <param name="stateActionDirector">Director for building the action.</param> /// <param name="targetState">Target which will be active after the action is processed.</param> internal void SetAction(AutomatonBuilderDirector stateActionDirector, AutomatonState targetState) { if (_byteTargets.Count > 0 || _byteActions.Count > 0) throw new NotSupportedException("Cannot set state action when byte target is available"); if (stateActionDirector == null) throw new ArgumentNullException("stateActionDirector"); _director = stateActionDirector; _targetState = targetState; }
/// <summary> /// Gets starting state for shared line blob reader. /// </summary> /// <returns>The state.</returns> private AutomatonState getSharedBlobLineReader() { if (_initialSharedBlobLineReader == null) _initialSharedBlobLineReader = CreateNewState(); return _initialSharedBlobLineReader; }
/// <summary> /// Creates expression which set next state for the automaton. /// </summary> /// <param name="state">State to set.</param> /// <returns>The created expression.</returns> internal Expression GoToState(AutomatonState state) { return MakeVoid( Expression.Block( Expression.Assign(StateStorage, Expression.Constant(state.Id)), Expression.Continue(MoveNextByteLabel) )); }
/// <summary> /// Creates new state for constructed automaton. /// </summary> /// <returns>Created state.</returns> internal AutomatonState CreateNewState() { var state = new AutomatonState(_registeredStates.Count); _registeredStates.Add(state); return state; }