File: Internal\SrgsCompiler\OneOf.cs
Web Access
Project: src\src\runtime\src\libraries\System.Speech\src\System.Speech.csproj (System.Speech)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#region Using directives

using System.Speech.Internal.SrgsParser;

#endregion

namespace System.Speech.Internal.SrgsCompiler
{
    internal class OneOf : ParseElementCollection, IOneOf
    {
        #region Constructors

        /// <summary>
        /// Process the 'one-of' element.
        /// </summary>
        public OneOf(Rule rule, Backend backend)
            : base(backend, rule)
        {
            // Create a start and end start.
            _startState = _backend.CreateNewState(rule);
            _endState = _backend.CreateNewState(rule);

            //Add before the start state an epsilon arc
            _startArc = _backend.EpsilonTransition(1.0f);
            _startArc.End = _startState;

            //Add after the end state an epsilon arc
            _endArc = _backend.EpsilonTransition(1.0f);
            _endArc.Start = _endState;
        }

        #endregion

        #region Internal Method

        /// <summary>
        /// Process the '/one-of' element.
        /// Connects all the arcs into an exit end point.
        ///
        /// Verify OneOf contains at least one child 'item'.
        /// </summary>
        void IElement.PostParse(IElement parentElement)
        {
            if (_startArc!.End!.OutArcs.IsEmpty)
            {
                XmlParser.ThrowSrgsException(SRID.EmptyOneOf);
            }

            // Remove the extraneous arc and state if possible at the start and end
            _startArc = TrimStart(_startArc, _backend);
            _endArc = TrimEnd(_endArc, _backend);

            // Connect the one-of to the parent
            base.PostParse((ParseElementCollection)parentElement);
        }

        #endregion

        #region Protected Method

        /// <summary>
        /// Adds a new arc to the one-of
        /// </summary>
        internal override void AddArc(Arc start, Arc end)
        {
            start = TrimStart(start, _backend);
            end = TrimEnd(end, _backend);

            State? endStartState = end.Start;
            State? startEndState = start.End;

            // Connect the previous arc with the 'start' set the insertion point
            if (start.IsEpsilonTransition && start.IsPropertylessTransition && startEndState != null && startEndState.InArcs.IsEmpty)
            {
                System.Diagnostics.Debug.Assert(start.End == startEndState);
                start.End = null;
                _backend.MoveOutputTransitionsAndDeleteState(startEndState, _startState);
            }
            else
            {
                start.Start = _startState;
            }

            // Connect with the epsilon transition at the end
            if (end.IsEpsilonTransition && end.IsPropertylessTransition && endStartState != null && endStartState.OutArcs.IsEmpty)
            {
                System.Diagnostics.Debug.Assert(end.Start == endStartState);
                end.Start = null;
                _backend.MoveInputTransitionsAndDeleteState(endStartState, _endState);
            }
            else
            {
                end.End = _endState;
            }
        }

        #endregion

        #region Protected Method

        private State _startState;
        private State _endState;

        #endregion
    }
}