/// <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); }
/// <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; }