예제 #1
0
파일: State.cs 프로젝트: calumgrant/slurp
        /// <summary>
        /// Gets the set of terminal symbols that could follow the nonterminal symbol s
        /// in the current item-set.
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public IEnumerable <ITerminalSymbol> Follows(INonterminalSymbol s)
        {
            var result = new HashSet <ITerminalSymbol>();

            foreach (var e in items.Where(i => !i.AtEnd && i.NextSymbol == s))
            {
                ProductionRule rule = e.Rule;

                int index;
                for (index = e.DotPosition + 1; index < rule.rhs.Length; ++index)
                {
                    foreach (var t in rule.rhs[index].First)
                    {
                        result.Add(t);
                    }
                    if (!rule.rhs[index].CanBeEmpty)
                    {
                        break;
                    }
                }

                if (index == rule.rhs.Length)
                {
                    // This wasn't documented properly I don't think
                    // Also add the lookahead of the matched item if the rule can match at the end of the rule.
                    result.Add(e.Lookahead[0]);
                }
            }

            return(result);
        }
예제 #2
0
        public State CreateInitialState(INonterminalSymbol s)
        {
            var state = new State();

            foreach (var rule in s.Rules)
            {
                state.items.Add(new Item(rule, 0));
            }

            ExpandClosure(state);
            return(state);
        }
예제 #3
0
        public State CreateInitialState(INonterminalSymbol s)
        {
            // Hack to find the "eof" symbol
            ITerminalSymbol eof = (ITerminalSymbol)s.Rules.First().rhs[1];

            var state = new State();

            foreach (var rule in s.Rules)
            {
                state.items.Add(new Item(rule, 0, eof));
            }

            return(state);
        }
예제 #4
0
 public void Reduce(Token next, object value, INonterminalSymbol pushedSymbol)
 {
     stack.Push(new StackItem(Current.nonterminalGotos[pushedSymbol.GotoIndex], value));
     Accept(next);
 }
예제 #5
0
        public Parser(INonterminalSymbol <Result> grammar, ParserGenerator algorithm, params Terminal[] whitespace)
        {
            strategy = algorithm switch
            {
                ParserGenerator.LR0 => new LR0ParserGenerator(),
                ParserGenerator.SLR => new SLRParserGenerator(),
                ParserGenerator.CLR => new CLRParserGenerator(),
                ParserGenerator.LALR => new LALRParserGenerator(),
                _ => throw new ArgumentException(nameof(algorithm))
            };

            visitedStates = new HashSet <State>(strategy);

            eof = Terminal.Eof;

            // Set up symbol metadata
            startSymbol = new Symbol <Result, Context>("start");
            startSymbol.Match(grammar, eof, (x, y) => x);

            symbols      = startSymbol.ReachableSymbols.ToList();
            terminals    = grammar.ReachableTerminals.ToList();
            nonterminals = symbols.OfType <INonterminalSymbol>().ToList();

            tokenizer = grammar.MakeTokenizer(whitespace);
            terminals.Add(eof);  // Ensure it's at the end

            // Set up terminals
            epsilon = Terminal.Empty;  // !! Dont think this is needed ??

            // Mark potentially empty symbols
            MarkCanBeEmpty();

            ComputeFirstSets();

            // Index all the rules

            int index = 0;

            rules = new List <ProductionRule>();
            rules.AddRange(nonterminals.SelectMany(s => s.Rules));

            foreach (var r in rules)
            {
                r.Index = index++;
            }

            index = 0;
            foreach (var t in terminals)
            {
                t.TerminalIndex = index++;
            }

            index = 0;
            foreach (var t in nonterminals)
            {
                t.GotoIndex = index++;
            }

            // Compute the state tables

            // The initial state.

            initialState = strategy.CreateInitialState(startSymbol);
            strategy.ExpandClosure(initialState);
            visitedStates.Add(initialState);

            // Compute transitions for the state

            ComputeGotos(initialState);
            // ComputeActions(initialState);

            // Compute actions for all states.

            foreach (var state in visitedStates)
            {
                ComputeActions(state);
            }
        }

        HashSet <State> visitedStates;