private static void PlaceReduceActions(GrammarCompilationContext context) { foreach (var state in context.States) { var finalizers = state.Items.Finalizers; var finalizer = finalizers.FirstOrDefault(); if (finalizers.Count == state.Items.Count && finalizers.All(x => x.Kernel.Reduction == finalizer.Kernel.Reduction)) { // State only has finalizers reducing to the same product. state.State.DefaultAction = new ReduceParserAction(finalizer.Kernel.Reduction); } else { // Determine what reduce action to apply based on the lookaheads. foreach (var item in finalizers) { foreach (var lookahead in item.Lookahead) { var reduceAction = new ReduceParserAction(item.Kernel.Reduction); ParserAction action; if (!state.State.Actions.TryGetValue(lookahead, out action)) { state.State.Actions[lookahead] = reduceAction; } else { // State already handles the lookahead, introduce reduce conflict. context.Conflicts.Add(new GrammarReductionConflict( state.State, lookahead, action, reduceAction)); } } } } } }
public GrammarCompilationResult(GrammarCompilationContext context, ParserAutomaton automaton) { CompilationContext = context; Automaton = automaton; }
private static void CreateLr0States(GrammarCompilationContext context) { foreach (var augmentedRoot in context.GrammarData.AugmentedRoots) { var initialState = CreateInitialState(context, augmentedRoot); context.InitialStates.Add(augmentedRoot, initialState); // Don't replace this with a foreach loop. States are being added on the fly. for (int i = 0; i < context.States.Count; i++) ExpandState(context, context.States[i]); ReplaceRootReductionWithAcceptance(augmentedRoot, initialState); } }
private static void ExpandState(GrammarCompilationContext context, IntermediateParserState state) { // Check for possible shifts. foreach (var shifter in state.Items.Shifters) { var currentElement = shifter.Kernel.Element; // Get all LR(1) items sharing the same grammar element, get or // create the state that corresponds to the shifted items, and create // a transition to that state. var shiftedKernels = from item in state.Items let kernel = item.Kernel where kernel.Element == currentElement select kernel.NextItem; var kernelsArray = shiftedKernels.ToArray(); var nextState = context.GetOrCreateState(kernelsArray); shifter.NextItem = nextState.Items.First(x => x.Kernel == shifter.Kernel.NextItem); context.GetOrCreateTransition(state, currentElement, nextState); if (!state.State.Actions.ContainsKey(currentElement)) { var action = new ShiftParserAction(nextState.State); var customActionElement = currentElement as CustomActionGrammarElement; if (customActionElement != null) action.CustomAction = customActionElement.Action; state.State.Actions[currentElement] = action; } } }
private static IntermediateParserState CreateInitialState(GrammarCompilationContext context, GrammarDefinition augmentedRoot) { // The initial state contains the very first LR(0) item, which is the augmented root '.Root'. var initialItem = context.GrammarData.GrammarReductionsMapping[augmentedRoot][0].Lr0Items[0]; var initialState = context.GetOrCreateState(new [] { initialItem }); return initialState; }
private static ParserAutomaton CreateAutomaton(GrammarCompilationContext context) { var automaton = new ParserAutomaton(context.GrammarData.Grammar); foreach (var initialState in context.InitialStates) automaton.InitialStates.Add((GrammarDefinition)initialState.Key.Rule.Switch[0][0], initialState.Value.State); automaton.DefaultInitialState = context.InitialStates[context.GrammarData.DefaultAugmentedRoot].State; automaton.States.AddRange(context.States.Select(x => x.State)); return automaton; }
private static void ConstructAugmentedGrammar(GrammarCompilationContext context) { // Augmented grammar is constructed as described in page 197 of // http://web.stanford.edu/class/archive/cs/cs143/cs143.1128/lectures/06/Slides06.pdf foreach (var state in context.States) { foreach (var item in state.Items) { if (!item.Kernel.IsInitializer) continue; var reduction = new AugmentedGrammarReduction() { Product = context.GetOrCreateAnnotatedElement(item.Kernel.Reduction.Product, state.OutgoingTransitions.GetOrDefault(item.Kernel.Reduction.Product)), Reduction = item.Kernel.Reduction }; for (var currentItem = item; !currentItem.Kernel.IsFinalizer; currentItem = currentItem.NextItem) { var element = currentItem.Kernel.Element; ParserTransition transition = null; var definition = element as GrammarDefinition; if (definition != null) transition = currentItem.State.OutgoingTransitions.GetOrDefault(element); var annotatedElement = context.GetOrCreateAnnotatedElement(element, transition); annotatedElement.Parents.Add(reduction); reduction.Sequence.Add(annotatedElement); } } } }
private static void ComputeLookaheads(GrammarCompilationContext context) { foreach (var state in context.States) { foreach (var item in state.Items) { if (!item.Kernel.IsInitializer) continue; var finalizer = item.GetFinalizer(); if (finalizer.State.Items.Count == 1) continue; var annotatedElement = context.GetAnnotatedGrammarElement(item.Kernel.Reduction.Product, state); if (annotatedElement!= null) finalizer.Lookahead.UnionWith(annotatedElement.GetFollowSet()); } } }
public static GrammarCompilationResult Compile(GrammarData grammarData) { if (grammarData == null) throw new ArgumentNullException(nameof(grammarData)); var context = new GrammarCompilationContext(grammarData); CreateLr0States(context); ConstructAugmentedGrammar(context); ComputeLookaheads(context); PlaceReduceActions(context); var automaton = CreateAutomaton(context); var result = new GrammarCompilationResult(context, automaton); return result; }