public void SetGetAction( int state_count, int terminal_count, int grammatical_count, int state_index, int terminal_index, ParserTable.Action action) { var t = new ParserTable(state_count, terminal_count, grammatical_count); t.SetAction(state_index, terminal_index, action); Assert.Equal(action, t.GetAction(state_index, terminal_index)); }
/// <summary> /// Builds and return an SLR(1) <see cref="ParserTable"/> based on the given paramaters. /// </summary> /// <param name="grammar">The grammar.</param> /// <param name="canonical_sets">LR(0) canonical sets generated from the <paramref name="grammar"/>.</param> /// <param name="follow_sets">Follow sets of all the <paramref name="grammar"/>'s grammaticals /// (see <see cref="FollowSets"/>).</param> /// <returns>An SLR(1) parser table.</returns> public static ParserTable Build( ExtendedGrammar grammar, LR0CanonicalSets canonical_sets, IDictionary<GrammaticalSymbol, ISet<TerminalSymbol>> follow_sets) { if( object.ReferenceEquals(grammar, null) ) throw new ArgumentNullException("grammar"); if( object.ReferenceEquals(canonical_sets, null) ) throw new ArgumentNullException("canonical_sets"); if( object.ReferenceEquals(follow_sets, null) ) throw new ArgumentNullException("follow_sets"); var table = new ParserTable(canonical_sets.Sets.Count, grammar.Terminals.Count, grammar.Grammaticals.Count); for( int state_index = 0; state_index < canonical_sets.Sets.Count; ++state_index ) { // Steps foreach( var term in grammar.Terminals ) { int next_state_index = canonical_sets.GetTransition(state_index, term); if( next_state_index != -1 ) { if( table.GetAction(state_index, grammar.IndexOf(term)).Type != ParserTable.ActionType.Error ) throw new ArgumentException("Grammar is not SLR(1)."); //TODO: custom exception with conflict info table.SetAction(state_index, grammar.IndexOf(term), ParserTable.Action.Step(next_state_index)); } } // Gotos foreach( var gram in grammar.Grammaticals ) { int next_state_index = canonical_sets.GetTransition(state_index, gram); if( next_state_index != -1 ) { if( table.GetGoto(state_index, grammar.IndexOf(gram)) != -1 ) throw new ArgumentException("Grammar is not SLR(1)."); //TODO: custom exception with conflict info table.SetGoto(state_index, grammar.IndexOf(gram), next_state_index); } } // Reductions foreach( var item in canonical_sets.Sets[state_index] ) if( item.CursorPosition == item.Rule.RightHandSide.Count ) { // Is it [S'->S.] ? if( item.Rule.LeftHandSide == grammar.StartSymbol ) { if( table.GetAction(state_index, grammar.IndexOf(grammar.EndOfSourceSymbol)).Type != ParserTable.ActionType.Error ) throw new ArgumentException("Grammar is not SLR(1)."); //TODO: custom exception with conflict info table.SetAction( state_index, grammar.IndexOf(grammar.EndOfSourceSymbol), ParserTable.Action.Accept()); } // ... no, it's [A->alpha.] else { int rule_index = grammar.Rules.IndexOf(item.Rule); foreach( var follow_term in follow_sets[item.Rule.LeftHandSide] ) { if( table.GetAction(state_index, grammar.IndexOf(follow_term)).Type != ParserTable.ActionType.Error ) throw new ArgumentException("Grammar is not SLR(1)."); //TODO: custom exception with conflict info table.SetAction( state_index, grammar.IndexOf(follow_term), ParserTable.Action.Reduction(rule_index)); } } } } return table; }