public Parser( CompiledGrammar <TLabel> grammar, IReadOnlyDictionary <Tuple <IDfa <Optional <Rule <TLabel> >, TLabel>, IState, TLabel>, ParseAction <TLabel> > table) { this.grammar = grammar; this.table = table; }
public static CompiledGrammar <TLabel> CompileGrammar(Grammar <TLabel> grammar) { var result = new CompiledGrammar <TLabel>(); result.StartSymbol = grammar.StartSymbol; result.Rules = grammar.Rules.GroupBy((rule) => rule.Lhs).ToDictionary( keySelector: (group) => group.Key, elementSelector: (group) => CompileRules(group.ToList())); return(result); }
public ParseProcess( CompiledGrammar <TLabel> grammar, IReadOnlyDictionary <Tuple <IDfa <Optional <Rule <TLabel> >, TLabel>, IState, TLabel>, ParseAction <TLabel> > table, IDiagnostics diagnostics) { this.rules = grammar.Rules; this.table = table; this.diagnostics = diagnostics; var startSymbol = grammar.StartSymbol; this.statesStack = new Stack <IState>(new[] { this.rules[startSymbol].StartingState() }); this.dfaStack = new Stack <IDfa <Optional <Rule <TLabel> >, TLabel> >(new[] { this.rules[startSymbol] }); this.nodesStack = new Stack <List <ParseTree <TLabel> > >(new[] { new List <ParseTree <TLabel> >() }); }
public static IReadOnlyDictionary <DfaAndState <Symbol>, IReadOnlyCollection <Symbol> > GetFirstSymbols( CompiledGrammar <Symbol> grammar, IReadOnlyCollection <DfaAndState <Symbol> > nullables) { var nullablesSet = new HashSet <DfaAndState <Symbol> >(nullables); var firstSymbols = new Dictionary <DfaAndState <Symbol>, HashSet <Symbol> >(); var graph = new Dictionary <DfaAndState <Symbol>, List <DfaAndState <Symbol> > >(); foreach (var rule in grammar.Rules) { var dfa = rule.Value; foreach (var state in DfaUtils.GetAllStates(dfa)) { var stateEntity = StateEntity(dfa, state); firstSymbols[stateEntity] = new HashSet <Symbol>(); graph[stateEntity] = new List <DfaAndState <Symbol> >(); foreach (var transition in dfa.Transitions(state)) { Symbol symbol = transition.Key; var nextState = transition.Value; if (dfa.Label(nextState).IsNone() && dfa.IsStable(nextState)) { continue; } firstSymbols[stateEntity].Add(symbol); if (!grammar.Rules.ContainsKey(symbol)) { continue; } var symbolEntity = StateEntity(grammar.Rules[symbol], grammar.Rules[symbol].StartingState()); graph[stateEntity].Add(symbolEntity); if (nullablesSet.Contains(symbolEntity)) { graph[stateEntity].Add(StateEntity(dfa, transition.Value)); } } } } TransitiveClosure(graph, firstSymbols); return(firstSymbols.ToDictionary(kpv => kpv.Key, kpv => kpv.Value as IReadOnlyCollection <Symbol>)); }
ParseAction <TLabel> > Parse( CompiledGrammar <TLabel> grammar, IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > follow, IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > firstPlus) { var parseTable = new Dictionary <Tuple <IDfa <Optional <Rule <TLabel> >, TLabel>, IState, TLabel>, ParseAction <TLabel> >(); var allSymbols = (TLabel[])Enum.GetValues(typeof(TLabel)); var error = string.Empty; foreach (var rule in grammar.Rules) { var dfa = rule.Value; var allStates = dfa.GetAllStates(); foreach (var state in allStates) { foreach (var firstSymbol in allSymbols) { var key = Tuple.Create(dfa, state, firstSymbol); var actions = GetAllParseActions(grammar, state, dfa, firstSymbol, follow, firstPlus); if (actions.Count > 1) { var errorMessage = $"Many possible actions for label {firstSymbol}: {{{string.Join(", ", actions)}}}\n"; error += errorMessage; } else if (actions.Count == 1) { parseTable[key] = actions.ElementAt(0); } } } } if (!error.Equals(string.Empty)) { throw new InvalidOperationException(error); } return(parseTable); }
public static IReadOnlyDictionary <DfaAndState <TLabel>, IReadOnlyCollection <TLabel> > GetFollowSymbols( CompiledGrammar <TLabel> grammar, IReadOnlyCollection <DfaAndState <TLabel> > nullables, IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > first, TLabel eofSymbol) { var resultSymbols = new Dictionary <TLabel, HashSet <TLabel> >(); GetDefault(resultSymbols, grammar.StartSymbol).Add(eofSymbol); var resultStates = new Dictionary <DfaAndState <TLabel>, HashSet <TLabel> >(); while (true) { bool anythingChanged = false; foreach (var rule in grammar.Rules) { var dfa = rule.Value; foreach (var state in DfaUtils.GetAllStates(dfa)) { var label = dfa.Label(state); var dfaAndState = new DfaAndState <TLabel> { Dfa = dfa, State = state }; var stateFollows = GetDefault(resultStates, dfaAndState); if (label.IsSome()) { var symFollows = GetDefault(resultSymbols, label.Get().Lhs); foreach (var sym in symFollows) { anythingChanged = stateFollows.Add(sym) || anythingChanged; } } foreach (var transition in dfa.Transitions(state)) { TLabel edgeSymbol = transition.Key; var nextState = transition.Value; var nextDfaAndState = new DfaAndState <TLabel> { Dfa = dfa, State = nextState }; if (dfa.Label(nextState).IsNone() && dfa.IsStable(nextState)) { continue; } anythingChanged = stateFollows.Add(edgeSymbol) || anythingChanged; // And also add First (first is the same as Follow of the initial state) if (grammar.Rules.ContainsKey(edgeSymbol)) { var edgeStartState = new DfaAndState <TLabel> { Dfa = grammar.Rules[edgeSymbol] }; edgeStartState.State = edgeStartState.Dfa.StartingState(); foreach (var sym in GetDefault(resultStates, edgeStartState)) { anythingChanged = stateFollows.Add(sym) || anythingChanged; } } var edgeFollows = GetDefault(resultSymbols, edgeSymbol); foreach (var sym in GetDefault(resultStates, nextDfaAndState)) { anythingChanged = edgeFollows.Add(sym) || anythingChanged; } } } } if (!anythingChanged) { break; } } var resultStatesCorrect = new Dictionary <DfaAndState <TLabel>, HashSet <TLabel> >(); // Contrary to expectations, resultStates doesn't contain correct follows for accepting states of the automatas, // because they can be reused. // To sum up: 'follow for states' doesn't make sense, only for symbols, but we fake 'follow for states' to conform with the API. foreach (var rule in grammar.Rules) { var dfa = rule.Value; foreach (var state in DfaUtils.GetAllStates(dfa)) { var label = dfa.Label(state); var dfaAndState = new DfaAndState <TLabel> { Dfa = dfa, State = state }; var stateFollows = GetDefault(resultStates, dfaAndState); if (label.IsSome()) { resultStatesCorrect[dfaAndState] = resultSymbols[label.Get().Lhs]; } } } return(resultStatesCorrect.ToDictionary(kpv => kpv.Key, kpv => kpv.Value as IReadOnlyCollection <TLabel>)); }
public static IReadOnlyCollection <DfaAndState <TLabel> > GetNullableSymbols(CompiledGrammar <TLabel> grammar) { // TLabel - nieterminal // Rule<TLabel> - produkcja var statesToProcess = new Queue <DfaAndState <TLabel> >(); var dfaToLhSymbol = new Dictionary <IDfa <Optional <Rule <TLabel> >, TLabel>, TLabel>(); var nullableSymbols = new HashSet <TLabel>(); var potentialNullableStates = new Dictionary <TLabel, List <DfaAndState <TLabel> > >(); var visitedStates = new HashSet <DfaAndState <TLabel> >(); // all visited states are nullable foreach (var rule in grammar.Rules) { var ruleDfa = rule.Value; foreach (var state in ruleDfa.GetAllStates()) { if (IsAccepting(ruleDfa, state)) { var queuePair = CreateDfaAndState(ruleDfa, state); if (!visitedStates.Contains(queuePair)) { visitedStates.Add(queuePair); statesToProcess.Enqueue(queuePair); } if (!dfaToLhSymbol.ContainsKey(ruleDfa)) { dfaToLhSymbol.Add(ruleDfa, rule.Key); } } } } var reverseTransitions = GetReverseTransitions(grammar); while (statesToProcess.Count > 0) { var queuePair = statesToProcess.Dequeue(); if (queuePair.State.Equals(queuePair.Dfa.StartingState())) { var lhSymbol = dfaToLhSymbol[queuePair.Dfa]; nullableSymbols.Add(lhSymbol); if (!potentialNullableStates.ContainsKey(lhSymbol)) { potentialNullableStates.Add(lhSymbol, new List <DfaAndState <TLabel> >()); } foreach (var stateDfaPair in potentialNullableStates[lhSymbol]) { if (!visitedStates.Contains(stateDfaPair)) { visitedStates.Add(stateDfaPair); statesToProcess.Enqueue(stateDfaPair); } } potentialNullableStates.Clear(); } foreach (var transition in reverseTransitions[queuePair.Dfa][queuePair.State]) { var symbol = transition.Key; foreach (var newState in transition.Value) { var newQueuePair = CreateDfaAndState(queuePair.Dfa, newState); if (visitedStates.Contains(newQueuePair)) { continue; } if (nullableSymbols.Contains(symbol)) { if (!visitedStates.Contains(newQueuePair)) { visitedStates.Add(newQueuePair); statesToProcess.Enqueue(newQueuePair); } } else { if (!potentialNullableStates.ContainsKey(symbol)) { potentialNullableStates.Add(symbol, new List <DfaAndState <TLabel> >()); } potentialNullableStates[symbol].Add(newQueuePair); } } } } return(visitedStates); }
private static IReadOnlyDictionary <IDfa <Optional <Rule <TLabel> >, TLabel>, Dictionary <IState, Dictionary <TLabel, HashSet <IState> > > > GetReverseTransitions(CompiledGrammar <TLabel> grammar) { var reverseTransitions = new Dictionary <IDfa <Optional <Rule <TLabel> >, TLabel>, Dictionary <IState, Dictionary <TLabel, HashSet <IState> > > >(); foreach (var rule in grammar.Rules) { reverseTransitions.Add(rule.Value, GetReverseTransitions(rule.Value)); } return(reverseTransitions); }
private static IReadOnlyCollection <ParseAction <TLabel> > GetAllParseActions( CompiledGrammar <TLabel> grammar, IState state, IDfa <Optional <Rule <TLabel> >, TLabel> dfa, TLabel label, IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > follow, IReadOnlyDictionary <TLabel, IReadOnlyCollection <DfaAndState <TLabel> > > firstPlus) { var actions = new List <ParseAction <TLabel> >(); var stateLabel = dfa.Label(state); var dfaAndState = new DfaAndState <TLabel>() { Dfa = dfa, State = state }; if (stateLabel.IsSome() && follow.ContainsKey(label) && follow[label].Contains(dfaAndState)) { actions.Add( new ParseAction <TLabel>() { Kind = ParseAction <TLabel> .ActionKind.Reduce, Label = stateLabel.Get().Lhs }); } var transitions = dfa.Transitions(state); if (transitions.ContainsKey(label)) { var nextState = transitions[label]; if (!dfa.IsStable(nextState) || dfa.Label(nextState).IsSome()) { actions.Add( new ParseAction <TLabel>() { Kind = ParseAction <TLabel> .ActionKind.Shift, Label = label }); } } if (firstPlus.ContainsKey(label)) { var firstPlusStates = firstPlus[label]; foreach (var transitionLabel in transitions.Keys) { var nextState = transitions[transitionLabel]; if ((!dfa.IsStable(nextState) || dfa.Label(nextState).IsSome()) && grammar.Rules.ContainsKey(transitionLabel)) { var subDfa = grammar.Rules[transitionLabel]; var subDfaAndStartState = new DfaAndState <TLabel>() { Dfa = subDfa, State = subDfa.StartingState() }; if (firstPlusStates.Contains(subDfaAndStartState)) { actions.Add( new ParseAction <TLabel>() { Kind = ParseAction <TLabel> .ActionKind.Call, Label = transitionLabel }); } } } } return(actions); }