Example #1
0
 private void ValidateNoUndeclaredNonterminal()
 {
     foreach (var item in Productions)
     {
         foreach (var nt in item.Body.Where(x => x is NonterminalSymbol).Cast <NonterminalSymbol>())
         {
             if (!Productions.Any(x => x.Head == nt))
             {
                 throw new GrammarException(new Location(), $"símbolo {nt} não declarado");
             }
         }
     }
 }
Example #2
0
        /// <summary>
        ///     Gets a collection of Terminal elements that can appear after the element that is after the dot of the item.
        /// </summary>
        /// <example>
        ///     With Grammar:
        ///     S -> E
        ///     E -> T
        ///     E -> (E)
        ///     T -> n
        ///     T -> + T
        ///     T ->  T + n
        ///     Follow(S -> •E) : {$}
        ///     Follow(T -> •+ T) : {'+', 'n'}
        ///     Follow(T -> •n, ')') : {')'}
        /// </example>
        /// <param name="nonTerminal"></param>
        /// <returns></returns>
        private IEnumerable <Terminal <T> > Follow(LRItem <T> item, IEnumerable <LRItem <T> > totalItems)
        {
            //Follow(item) is First(b) where item is:
            //A -> a•Eb

            GrammarElement <T> element = item.GetNextElement(1);

            if (element != null)
            {
                if (element is NonTerminal <T> )
                {
                    var firstSet = new List <Terminal <T> >();

                    //if the element has a production with no derived elements and the element is at the end of the current item's production, then
                    //add the lookahead of the given item.

                    //if there is any production of the current element that has no derived elements
                    if (Productions.Any(a => a.NonTerminal.Equals(element) && a.DerivedElements.Count == 0))
                    {
                        //if the current element is the end of the current item's production
                        if (item.GetNextElement(2) == null)
                        {
                            firstSet.Add(item.LookaheadElement ?? EndOfInputElement);
                        }
                    }

                    //select the lookahead element or end of input element for each item in the previous set
                    //List<Terminal<T>> firstSet = new List<Terminal<T>>(items.Select(a => a.LookaheadElement == null ? EndOfInputElement : a.LookaheadElement));

                    //add the rest of the first set.
                    firstSet.AddRange(First(element));
                    return(firstSet);
                }
                return(First(element));
            }
            if (item.LookaheadElement == null)
            {
                return new[] { EndOfInputElement }
            }
            ;
            return(new[] { item.LookaheadElement });
        }