Example #1
0
        private void SolveLeftRecursion(IEnumerable <Symbol>[] alphas)
        {
            if (alphas.Length == 0)
            {
                return;
            }

            var primeSymbol = Grammer.AddRule();

            primeSymbol.RHSList.Add(Expression.E);
            foreach (var alpha in alphas)
            {
                primeSymbol.RHSList.Add(Expression.Create(alpha.Append(primeSymbol)));
            }

            var betas = RHSList.Where(e => e.Value[0] != this).ToArray();

            RHSList.Clear();
            foreach (var beta in betas)
            {
                if (beta.IsEpsilon)
                {
                    RHSList.Add(Expression.Create(primeSymbol));
                }
                else
                {
                    RHSList.Add(beta.Append(primeSymbol));
                }
            }
            //here we should apply left factoring on the prime symbol but the Grammer will do that.
        }
Example #2
0
        internal void SetRHS(string rhs)
        {
            RHSList.Clear();
            var expressions = rhs.Replace(" ", "").Split(new char[] { Grammer.ExpressionSeperator }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var expText in expressions)
            {
                RHSList.Add(Expression.Create(expText.Select(s => Grammer.Symbols[s])));
            }
        }
Example #3
0
        internal IReadOnlyCollection <TerminalSymbol> FindFirst(HashSet <NonTerminalSymbol> path)
        {
            if (path.Add(this) == false || First.Count > 0)
            {
                return(First);
            }

            foreach (var exp in RHSList.OrderBy(e => e[0] is TerminalSymbol ? 0 : 1))
            {
                bool doneFromExpression = false;
                foreach (var symbol in exp)
                {
                    switch (symbol)
                    {
                    case TerminalSymbol terminal:
                        _first.Add(terminal);
                        doneFromExpression = true;
                        break;

                    case NonTerminalSymbol nonTerminal:
                        foreach (var firstSymbol in nonTerminal.FindFirst(path).Except(new TerminalSymbol[] { Epsilon.E }))
                        {
                            _first.Add(firstSymbol);
                        }
                        if (nonTerminal.First.Contains(Epsilon.E) == false)
                        {
                            doneFromExpression = true;
                        }
                        break;

                    default:
                        break;
                    }
                    if (doneFromExpression)
                    {
                        break;
                    }
                }
                if (doneFromExpression == false)
                {
                    _first.Add(Epsilon.E);
                }
            }

            path.Remove(this);
            return(First);
        }
Example #4
0
        internal void ApplyLeftFactoring()
        {
            var trie = TrieNode.CreateRoot();

            foreach (var exp in RHSList)
            {
                if (exp.IsEpsilon)
                {
                    continue;
                }
                trie.AddExpression(exp);
            }
            var alphas = trie.GetMinCommonExpressions();

            alphas.Add(Expression.E);
            var groupedExpressions = alphas.ToDictionary(a => a, a => new List <Expression>());

            //Group them by there alpha and if non then epsilon is its alpha
            foreach (var exp in RHSList)
            {
                var expAlpha = alphas.FirstOrDefault(a => exp.StartsWith(a)) ?? Expression.E;
                groupedExpressions[expAlpha].Add(exp);
            }

            RHSList.Clear();
            var primes = new List <NonTerminalSymbol>();

            foreach (var grp in groupedExpressions)
            {
                if (grp.Key == Expression.E)
                {
                    RHSList.AddRange(grp.Value);
                }
                else
                {
                    var primeSymbol = Grammer.AddRule();
                    primeSymbol.RHSList.AddRange(grp.Value.Select(e => e.SubExpression(grp.Key.Count)));
                    RHSList.Add(Expression.Create(grp.Key.Value.Append(primeSymbol)));
                    primes.Add(primeSymbol);
                }
            }
            foreach (var prime in primes)
            {
                prime.ApplyLeftFactoring();
            }
        }
Example #5
0
        /// <remarks>Solves only 1-level indirect recursion</remarks>
        internal void SolveIndirectLeftRecusrion()
        {
            var newRHS = new List <Expression>(RHSList.Count + 10);

            foreach (var exp in RHSList)
            {
                if ((exp[0] as NonTerminalSymbol)?.RHSList.Any(re => re.Value[0] == this) ?? false)
                {
                    newRHS.AddRange((exp[0] as NonTerminalSymbol).RHSList.Select(re => re.Append(exp.SubExpression(1))));
                }
                else
                {
                    newRHS.Add(exp);
                }
            }
            RHSList.Clear();
            RHSList.AddRange(newRHS);
            SolveLeftRecursion(CalcAlphas());
        }
Example #6
0
 private IEnumerable <Symbol>[] CalcAlphas() => RHSList.Where(e => e.Value[0] == this)
 .Select(e => e.Value.Skip(1))
 .ToArray();