public bool CheckSyntax(IEnumerable <Token> tokens)
        {
            var precedenceTable = _helper.GetPrecedenceTable(Grammar);
            var tokensList      = tokens as List <Token> ?? tokens.ToList();

            var sharp = TokenEnum.Sharp;

            sharp.Line = tokensList[tokensList.Count - 1].Line;
            tokensList.Add(sharp);
            var tokensArray = tokensList.ToArray();
            var array       = tokensArray.Select(t =>
            {
                if (t is TokenEnum)
                {
                    return(t);
                }
                var tEnum =
                    Grammar.SelectMany(x => x.CompositeToken)
                    .Cast <TokenEnum>()
                    .FirstOrDefault(x => x.IsTheSame(t))?.Clone() as TokenEnum;

                if (tEnum != null)
                {
                    tEnum.Line = t.Line;
                }

                return(tEnum);
            }).ToArray();

            if (array.Any(x => x == null))
            {
                Logger.Error("Unknown token: {0}", tokensArray[Array.FindIndex(array, x => x == null)]);
            }

            var stack = new Stack <Token>();

            stack.Push(TokenEnum.Sharp);

            var i      = 0;
            var popped = new List <Token>();

            Prn = new List <Token>();
            while (stack.Peek().Type != TokenType.Axiom || array[i] != TokenEnum.Sharp)
            {
                try
                {
                    var relation = precedenceTable[stack.Peek()][array[i]];
                    if (relation == PrecedenceRelation.More)
                    {
                        //Base search
                        popped.Clear();
                        popped.Add(stack.Pop());
                        while (precedenceTable[stack.Peek()][popped.Last()] != PrecedenceRelation.Less)
                        {
                            popped.Add(stack.Pop());
                        }

                        popped.Reverse();
                        try
                        {
                            var toReplace = Grammar.First(x => x.CompositeToken.SequenceEqual(popped));
                            toReplace.OnReplaceAction?.Invoke(tokensArray.Skip(i - popped.Count).Take(popped.Count).ToList(), Prn);
                            PRNChanged?.Invoke(toReplace.Token, Prn);
                            stack.Push(toReplace.Token);
                        }
                        catch (Exception exc)
                        {
                            Logger.Error("Can't replace sequence {0}, Line = {1}", popped, array[i].Line);
                            return(false);
                        }
                    }
                    else
                    //Copy the symbol to stack
                    {
                        stack.Push(array[i++]);
                    }

                    OnStackChanged(stack, relation.Value,
                                   new ArraySegment <Token>(tokensArray, i, tokensArray.Length - i), Prn);
                }
                catch
                {
                    Logger.Error("There is no relation for a pair {0}-{1}, Line = {2}", stack.Peek(), array[i],
                                 array[i].Line);
                    return(false);
                }
            }

            return(true);
        }
 protected virtual void OnPrnChanged(Token tokenReplaced, List <Token> prn)
 {
     PRNChanged?.Invoke(tokenReplaced, prn);
 }