Пример #1
0
        private static Nonterminal Reduce(ParserStack stack, RuleType rule)
        {
            // Create a language element array big enough to hold the LHS and RHS
            // arguments.
            //
            int parameterCount = 1 + rule.Rhs.Length;

            LanguageElement[] parameters = new LanguageElement[parameterCount];

            // Create the LHS nonterminal.
            //
            Nonterminal lhs = rule.Lhs.CreateNonterminal();

            parameters[0] = lhs;

            // Pop the RHS language elements off the stack.
            //
            for (int idx = 0; idx < rule.Rhs.Length; ++idx)
            {
                parameters[parameterCount - idx - 1] = stack.Pop().LanguageElement;
            }

            // Invoke the rule.
            //
            rule.Invoke(parameters);
            return(lhs);
        }
Пример #2
0
        /// <summary>
        /// Constructs an instance of a <see cref="Nonterminal"/> described by this <see cref="NonterminalType"/>.
        /// </summary>
        /// <returns>A new <see cref="Nonterminal"/>.</returns>
        public Nonterminal CreateNonterminal()
        {
            Nonterminal result = m_constructor();

            result.ElementType = this;
            return(result);
        }
Пример #3
0
        /// <summary>
        /// Performs syntax analysis against a sequence of terminals according to the <see cref="Grammar"/> used to create the <see cref="Parser"/>.
        /// </summary>
        /// <param name="terminalReader">Retrieves a sequence of <see cref="Terminal"/> objects.</param>
        /// <returns>If syntax analysis succeeds, returns the <see cref="Nonterminal"/> associated with <see cref="Grammar.StartNonterminal"/>.  Otherwise, <value>null</value> is returned.</returns>
        public Nonterminal Parse(ITerminalReader terminalReader)
        {
            ParserStack stack = new ParserStack();

            stack.Push(null, InitialState);

            Terminal terminal = terminalReader.ReadTerminal();

            while (terminal != null)
            {
                if (terminal.ElementType.Ignore)
                {
                    terminal = terminalReader.ReadTerminal();
                }
                else
                {
                    ParserAction action = stack.Peek().State.GetAction(terminal.ElementType);

                    LinguaTrace.TraceEvent(TraceEventType.Information, LinguaTraceId.ID_PARSE_ACTION, "{0}", action);

                    if (action == null)
                    {
                        return(null);
                    }

                    switch (action.ActionType)
                    {
                    case ParserActionTypes.Accept:
                    {
                        ParserActionAccept reduce = (ParserActionAccept)action;
                        RuleType           rule   = reduce.Rule;

                        Nonterminal lhs = Reduce(stack, rule);

                        return(lhs);
                    }

                    case ParserActionTypes.Shift:
                    {
                        ParserActionShift shift = (ParserActionShift)action;

                        stack.Push(terminal, shift.State);

                        terminal = terminalReader.ReadTerminal();
                    }
                    break;

                    case ParserActionTypes.Reduce:
                    {
                        ParserActionReduce reduce = (ParserActionReduce)action;
                        RuleType           rule   = reduce.Rule;

                        Nonterminal lhs = Reduce(stack, rule);

                        // Push the LHS nonterminal on the stack.
                        //
                        stack.Push(lhs, stack.Peek().State.GetGoto(lhs.ElementType));
                    }
                    break;

                    default:
                        throw new InvalidOperationException(string.Format("Unrecognized action type {0}.", action.ActionType));
                    }
                }
            }
            ;

            return(null);
        }