Exemple #1
0
        private static SwitchExpression CompileState <OutputT>(TransducerState <Char, OutputT> state, ParameterExpression reader, ParameterExpression output, LabelTarget @return, Int32 depth)
        {
            var idx   = 0;
            var cases = new SwitchCase[state.TransitionTable.Count];

            foreach (KeyValuePair <Char, TransducerState <Char, OutputT> > statePair in state.TransitionTable)
            {
                cases[idx++] = Expression.SwitchCase(
                    CompileState(statePair.Value, reader, output, @return, depth + 1),
                    Expression.Constant((Char?)statePair.Key)
                    );
            }

            return(Expression.Switch(
                       GExpression.MethodCall <ICodeReader>(reader, r => r.Peek(depth), depth),
                       state.IsTerminal
                    ? Expression.Block(
                           GExpression.MethodCall <ICodeReader>(reader, r => r.Advance(0), depth + 1),
                           Expression.Assign(output, Expression.Constant(state.Output)),
                           Expression.Return(@return, Expression.Constant(true))
                           )
                    : (Expression)Expression.Return(@return, Expression.Constant(false)),
                       cases
                       ));
        }
Exemple #2
0
        private static SwitchExpression CompileState <TTokenType, OutputT>(TransducerState <Token <TTokenType>, OutputT> state, ParameterExpression reader, ParameterExpression output, LabelTarget @return, Int32 depth)
            where TTokenType : notnull
        {
            var idx   = 0;
            var cases = new SwitchCase[state.TransitionTable.Count];

            foreach (KeyValuePair <Token <TTokenType>, TransducerState <Token <TTokenType>, OutputT> > statePair in state.TransitionTable)
            {
                cases[idx++] = Expression.SwitchCase(
                    CompileState(statePair.Value, reader, output, @return, depth + 1),
                    Expression.Constant(statePair.Key)
                    );
            }

            return(Expression.Switch(
                       GExpression.MethodCall <ITokenReader <TTokenType> >(reader, r => r.Lookahead(depth), depth),
                       state.IsTerminal
                    ? Expression.Block(
                           GExpression.MethodCall <ITokenReader <TTokenType> >(reader, r => r.Skip(0), depth + 1),
                           Expression.Assign(output, Expression.Constant(state.Output)),
                           Expression.Return(@return, Expression.Constant(true))
                           )
                    : (Expression)Expression.Constant(false),
                       cases
                       ));
        }
Exemple #3
0
        /// <summary>
        /// Attempts to execute a transducer with content from a <see cref="StringCodeReader" />. If the
        /// state reached is not a terminal state, the reader is rewinded to it's initial position.
        /// </summary>
        /// <typeparam name="OutputT"></typeparam>
        /// <param name="transducer"></param>
        /// <param name="reader"></param>
        /// <param name="output"></param>
        /// <returns>Whether the state reached was a terminal state.</returns>
        public static Boolean TryExecute <OutputT>(this Transducer <Char, OutputT> transducer, ICodeReader reader, [MaybeNull] out OutputT output)
        {
            if (transducer is null)
            {
                throw new ArgumentNullException(nameof(transducer));
            }
            if (reader is null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var start = reader.Position;
            TransducerState <Char, OutputT> state = transducer.InitialState;

            while (reader.Position != reader.Length)
            {
                if (!state.TransitionTable.TryGetValue(reader.Peek() !.Value, out TransducerState <Char, OutputT>?tmp))
                {
                    break;
                }
                state = tmp;
                reader.Advance(1);
            }

            if (state.IsTerminal)
            {
                output = state.Output;
                return(true);
            }

            reader.Restore(start);
            // Since the analyzer doesn't seems to obey [MaybeNull], we ignore the warning
            output = default;
            return(false);
        }
Exemple #4
0
        /// <summary>
        /// Attempts to execute the state machine against the <see cref="TokenReader{TTokenType}" />
        /// </summary>
        /// <typeparam name="TTokenType"></typeparam>
        /// <typeparam name="OutputT"></typeparam>
        /// <param name="transducer"></param>
        /// <param name="reader"></param>
        /// <param name="output"></param>
        /// <returns></returns>
        public static Boolean TryExecute <TTokenType, OutputT>(this Transducer <Token <TTokenType>, OutputT> transducer, ITokenReader <TTokenType> reader, [MaybeNull] out OutputT output)
            where TTokenType : notnull
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            var offset = 0;
            TransducerState <Token <TTokenType>, OutputT> state = transducer.InitialState;

            while (reader.Position < reader.Length)
            {
                if (!state.TransitionTable.TryGetValue(reader.Lookahead(offset), out TransducerState <Token <TTokenType>, OutputT>?tmp))
                {
                    break;
                }
                state = tmp;
                offset++;
            }

            if (state.IsTerminal)
            {
                reader.Skip(offset + 1);
                output = state.Output;
                return(true);
            }

            output = default;
            return(false);
        }