Ejemplo n.º 1
0
        public Production(Nonterminal head, IEnumerable <Symbol> tail)
        {
            Head = head ?? throw new ArgumentNullException(nameof(head));
            var rhs = (tail ?? Enumerable.Empty <Symbol>()).ToArray();

            if (rhs.Length > 1 && rhs.Any(symbol => symbol.IsEpsilon))
            {
                throw new ArgumentException($"{Symbol.Epsilon}-productions cannot have more than one symbol.");
            }
            if (rhs.Length == 0 || rhs.Length == 1 && rhs[0].IsEpsilon)
            {
                Tail = Array.Empty <Symbol>();
            }
            else
            {
                Tail = rhs;
            }
        }
Ejemplo n.º 2
0
        public Grammar(
            SymbolCache <TTokenKind, Terminal <TTokenKind> > terminals,
            SymbolCache <TNonterminal, Nonterminal> nonterminals,
            Nonterminal startSymbol,
            IEnumerable <Production> productions,
            Func <Grammar <TTokenKind, TNonterminal>, IFollowSymbolsAnalyzer <TTokenKind> > analyzerFactory)
        {
            if (productions == null)
            {
                throw new ArgumentNullException(nameof(productions));
            }

            StartSymbol = startSymbol ?? throw new ArgumentNullException(nameof(startSymbol));

            Nonterminals = nonterminals ?? throw new ArgumentNullException(nameof(nonterminals));
            Terminals    = terminals ?? throw new ArgumentNullException(nameof(terminals));

            // Productions are numbered 0,1,2,...,^Productions.Count
            var prods = new List <Production>();
            // Variables (productions on the shorter form (A -> α | β | ...) are numbered 0,1,...,^Variables.Count
            var productionMap = Nonterminals.ToDictionary(symbol => symbol, _ => new List <(int, Production)>());

            int index = 0;

            foreach (var production in productions)
            {
                prods.Add(production);
                productionMap[production.Head].Add((index, production));
                index += 1;
            }

            ProductionsFor = productionMap.ToImmutableDictionary(kvp => kvp.Key,
                                                                 kvp => (IReadOnlyList <(int, Production)>)kvp.Value);

            if (prods.Count == 0)
            {
                throw new ArgumentException("The productions are empty.", nameof(productions));
            }

            Productions = prods;

            // Calculate lookahead sets (Erasable, First, Follow) using strategy provided by the caller
            _analyzer = analyzerFactory(this);
        }
Ejemplo n.º 3
0
 internal LrGotoEntry(int sourceState, Nonterminal nonterminalSymbol, int targetState)
 {
     SourceState       = sourceState;
     NonterminalSymbol = nonterminalSymbol;
     TargetState       = targetState;
 }