示例#1
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);
        }
示例#2
0
        /// <summary>
        /// Constructs a new <see cref="Parser"/> which can recoganize the specified <see cref="IGrammar"/>.
        /// </summary>
        /// <param name="grammar">The <see cref="IGrammar"/> to be recognized by the <see cref="Parser"/>.</param>
        /// <returns>A <see cref="ParserGeneratorResult"/> containing <see cref="Parser"/> and information pertaining to the
        /// success or failure of the generation process.
        /// </returns>
        public ParserGeneratorResult GenerateParser(IGrammar grammar)
        {
            List <ParserGeneratorParserConflict> conflicts = new List <ParserGeneratorParserConflict>();

            List <GeneratorState> states = CreateStates(grammar);

            // Create a parser state for each generator state.
            //
            Dictionary <GeneratorState, ParserState> parserStates = new Dictionary <GeneratorState, ParserState>();

            foreach (GeneratorState state in states)
            {
                parserStates.Add(state, new ParserState(state.Id));
            }

            foreach (GeneratorState state in states)
            {
                LinguaTrace.TraceEvent(TraceEventType.Verbose, LinguaTraceId.ID_GENERATE_PROCESS_STATE, "{0}", state);

                List <GeneratorStateItem> items = new List <GeneratorStateItem>(state.Items);
                items.Sort();

                // Construct the list of actions associated with the parser state.
                //
                Dictionary <TerminalType, ParserAction>      actions     = new Dictionary <TerminalType, ParserAction>();
                Dictionary <ParserAction, GeneratorRuleItem> actionRules = new Dictionary <ParserAction, GeneratorRuleItem>();
                foreach (GeneratorStateItem item in items)
                {
                    LinguaTrace.TraceEvent(TraceEventType.Verbose, LinguaTraceId.ID_GENERATE_PROCESS_ITEM, "{0}", item);

                    if (item.RuleItem.DotElement == null)
                    {
                        foreach (TerminalType terminal in item.RuleItem.Rule.Lhs.Follow)
                        {
                            LinguaTrace.TraceEvent(TraceEventType.Verbose, LinguaTraceId.ID_GENERATE_PROCESS_TERMINAL, "{0}", terminal);

                            if (actions.ContainsKey(terminal))
                            {
                                ParserGeneratorParserConflict conflict = new ParserGeneratorParserConflict(
                                    actionRules[actions[terminal]].ToString(),
                                    item.RuleItem.ToString());

                                LinguaTrace.TraceEvent(TraceEventType.Information, LinguaTraceId.ID_GENERATE_PROCESS_CONFLICT, "{0}", conflict);

                                conflicts.Add(conflict);
                            }
                            else if (item.RuleItem.Rule.Lhs.IsStart &&
                                     terminal.IsStop)
                            {
                                ParserAction action = new ParserActionAccept(item.RuleItem.Rule);

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

                                actions.Add(terminal, action);
                                actionRules.Add(action, item.RuleItem);
                            }
                            else
                            {
                                ParserAction action = new ParserActionReduce(item.RuleItem.Rule);

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

                                actions.Add(terminal, action);
                                actionRules.Add(action, item.RuleItem);
                            }
                        }
                    }
                    else if (item.RuleItem.DotElement.ElementType == LanguageElementTypes.Terminal)
                    {
                        TerminalType terminal = (TerminalType)item.RuleItem.DotElement;

                        if (actions.ContainsKey(terminal))
                        {
                            ParserGeneratorParserConflict conflict = new ParserGeneratorParserConflict(
                                actionRules[actions[terminal]].ToString(),
                                item.RuleItem.ToString());

                            LinguaTrace.TraceEvent(TraceEventType.Information, LinguaTraceId.ID_GENERATE_PROCESS_CONFLICT, "{0}", conflict);

                            conflicts.Add(conflict);
                        }
                        else
                        {
                            ParserAction action = new ParserActionShift(parserStates[state.Transitions[terminal]]);

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

                            actions.Add(terminal, action);
                            actionRules.Add(action, item.RuleItem);
                        }
                    }
                }

                // Construct the GOTO table
                //
                Dictionary <NonterminalType, ParserState> gotos = new Dictionary <NonterminalType, ParserState>();
                foreach (KeyValuePair <LanguageElementType, GeneratorState> transition in state.Transitions)
                {
                    if (transition.Key.ElementType == LanguageElementTypes.Nonterminal)
                    {
                        NonterminalType nonterminal = (NonterminalType)transition.Key;
                        gotos.Add(nonterminal, parserStates[transition.Value]);
                    }
                }

                // Update the parser state.
                //
                ParserState parserState = parserStates[state];
                foreach (KeyValuePair <TerminalType, ParserAction> action in actions)
                {
                    parserState.Actions.Add(action.Key, action.Value);
                }

                foreach (KeyValuePair <NonterminalType, ParserState> gotoItem in gotos)
                {
                    parserState.Gotos.Add(gotoItem.Key, gotoItem.Value);
                }
            }

            Parser parser = new Parser(parserStates[states[0]]);

            ParserGeneratorResult result = new ParserGeneratorResult(parser, conflicts);

            return(result);
        }