public static bool AllPathsReturns(SyntaxTreeNode rootNode)
        {
            bool hasReturnOnRoot = rootNode.Children.Any(node => node.Value == Symbols.SRetorno);

            if (hasReturnOnRoot)
            {
                return true;
            }

            return InternalAllPathsReturns(rootNode);
        }
        private static bool InternalAllPathsReturns(SyntaxTreeNode node)
        {
            var foundReturn = true;

            foreach (var child in node.Children)
            {
                var rootReturn = child.Children.Any(childNode => childNode.Value == Symbols.SRetorno);

                if (rootReturn)
                {
                    return foundReturn & rootReturn;
                }

                foundReturn &= InternalAllPathsReturns(child);
            }

            return node.Children.Count > 0 && foundReturn;
        }
        private void AnalyzeFuncDcl()
        {
            _isAnalyzingFunction = true;
            NextToken();

            if (_token.Symbol != Symbols.SIdentificador)
            {
                RaiseUnexpectedTokenError("identificador");
            }

            var item = _symbolTable.Search(_token.Lexeme);

            if (item != null)
            {
                RaiseDoubleError(Symbols.SFuncao);
            }

            var funcItem = new FunctionItem
            {
                Lexeme = _token.Lexeme,
                Level  = _level,
                Label  = _codeGenerator.GetStringLabelFor(_lastLabel)
            };

            _funcInfo = new FunctionInfo {
                Name = _token.Lexeme
            };
            _rootNode = new SyntaxTreeNode {
                Value = _token.Symbol
            };
            _currentNode = _rootNode;
            _codeGenerator.GenerateLabel(_lastLabel);
            _level++;
            NextToken();

            if (_token.Symbol != Symbols.SDoisPontos)
            {
                RaiseUnexpectedTokenError("\":\"");
            }

            NextToken();

            if (_token.Symbol != Symbols.SInteiro && _token.Symbol != Symbols.SBooleano)
            {
                RaiseUnexpectedTokenError("\"inteiro\" ou \"booleano\"");
            }

            var type = _token.Symbol == Symbols.SInteiro ? ItemType.Integer : ItemType.Boolean;

            funcItem.Type = type;
            _symbolTable.Insert(funcItem);
            NextToken();

            if (_token.Symbol != Symbols.SPontoVirgula)
            {
                RaiseMissingSemicolonError();
            }

            AnalyzeBlock(true);

            if (!FunctionHelper.AllPathsReturns(_rootNode))
            {
                RaiseMissingFunctionReturn();
            }

            _symbolTable.CleanUpToLevel(_level);
            _level--;
            _rootNode = _currentNode = null;
            _funcInfo = null;
        }
        private void AnalyzeFuncDcl()
        {
            _isAnalyzingFunction = true;
            NextToken();

            if (_token.Symbol != Symbols.SIdentificador)
            {
                RaiseUnexpectedTokenError("identificador");
            }

            var item = _symbolTable.Search(_token.Lexeme);

            if (item != null)
            {
                RaiseDoubleError(Symbols.SFuncao);
            }

            var funcItem = new FunctionItem
            {
                Lexeme = _token.Lexeme,
                Level = _level,
                Label = _codeGenerator.GetStringLabelFor(_lastLabel)
            };
            
            _funcInfo = new FunctionInfo { Name = _token.Lexeme };
            _rootNode = new SyntaxTreeNode { Value = _token.Symbol };
            _currentNode = _rootNode;
            _codeGenerator.GenerateLabel(_lastLabel);
            _level++;
            NextToken();

            if (_token.Symbol != Symbols.SDoisPontos)
            {
                RaiseUnexpectedTokenError("\":\"");
            }

            NextToken();

            if (_token.Symbol != Symbols.SInteiro && _token.Symbol != Symbols.SBooleano)
            {
                RaiseUnexpectedTokenError("\"inteiro\" ou \"booleano\"");
            }

            var type = _token.Symbol == Symbols.SInteiro ? ItemType.Integer : ItemType.Boolean;

            funcItem.Type = type;
            _symbolTable.Insert(funcItem);
            NextToken();

            if (_token.Symbol != Symbols.SPontoVirgula)
            {
                RaiseMissingSemicolonError();
            }

            AnalyzeBlock(true);
            
            if (!FunctionHelper.AllPathsReturns(_rootNode))
            {
                RaiseMissingFunctionReturn();
            }
            
            _symbolTable.CleanUpToLevel(_level);
            _level--;
            _rootNode = _currentNode = null;
            _funcInfo = null;
        }
        private void AnalyzeSimpleCommand(bool isFunction = false)
        {
            if (_token.Symbol == Symbols.SIdentificador)
            {
                var item = _symbolTable.Search(_token.Lexeme);

                if (item == null)
                {
                    RaiseNotFoundIdentificatorError(_token.Lexeme);
                }

                _analyzingLexeme = _token.Lexeme;

                var funcItem = item as FunctionItem;

                if (_funcInfo != null && funcItem?.Lexeme == _funcInfo.Name)
                {
                    NextToken();

                    if (_token.Symbol == Symbols.SAtribuicao)
                    {
                        AnalyzeAttribution();
                    }
                    else
                    {
                        throw new CompilationException(string.Format(WrongFunctionCall, _lexical.Position.Line, _lexical.Position.Column));
                    }

                    if (isFunction)
                    {
                        _currentNode = _rootNode;
                    }

                    if (_currentNode != null)
                    {
                        _currentNode.Children.Add(new SyntaxTreeNode
                        {
                            Parent = _currentNode,
                            Value  = Symbols.SRetorno
                        });
                    }

                    _codeGenerator.GenerateInstruction(RETURNF, _funcInfo.FirstVarAddress, _funcInfo.VarsCount);
                }
                else
                {
                    NextToken();

                    if (_token.Symbol == Symbols.SAtribuicao)
                    {
                        AnalyzeAttribution();
                    }
                    else
                    {
                        AnalyzeProcCall();
                    }
                }
            }
            else if (_token.Symbol == Symbols.SSe)
            {
                AnalyzeIf();
            }
            else if (_token.Symbol == Symbols.SEnquanto)
            {
                AnalyzeWhile();
            }
            else if (_token.Symbol == Symbols.SLeia)
            {
                AnalyzeRead();
            }
            else if (_token.Symbol == Symbols.SEscreva)
            {
                AnalyzeWrite();
            }
            else
            {
                AnalyzeCommands();
            }
        }
 private SyntaxTreeNode GetNode(SyntaxTreeNode parent)
 {
     return new SyntaxTreeNode
     {
         Parent = parent,
         Value = _token.Symbol
     };
 }
        private void AnalyzeIf()
        {
            uint firstLabel;
            uint secondLabel;
            SyntaxTreeNode node = null;
            SyntaxTreeNode parent = null;

            if (_funcInfo != null && _isAnalyzingFunction)
            {
                parent = _currentNode ?? _rootNode ?? new SyntaxTreeNode();
                node = GetNode(parent);
                parent.Children.Add(node);
                _currentNode = node;
            }

            firstLabel = secondLabel = _lastLabel;
            _lastLabel++;
            NextToken();

            var expressionType = AnalyzeExpressionType();

            if (expressionType != ItemType.Boolean)
            {
                RaiseIncompatibleTypeError();
            }

            _codeGenerator.GenerateInstruction(JMPF, _codeGenerator.GetStringLabelFor(firstLabel));

            if (_token.Symbol != Symbols.SEntao)
            {
                RaiseUnexpectedTokenError("\"entao\"");
            }
            
            NextToken();
            AnalyzeSimpleCommand();

            if (_token.Symbol == Symbols.SSenao)
            {
                secondLabel = _lastLabel;
                _lastLabel++;
                _codeGenerator.GenerateInstruction(JMP, _codeGenerator.GetStringLabelFor(secondLabel));
                _codeGenerator.GenerateLabel(firstLabel);

                if (_funcInfo != null)
                {
                    node = GetNode(parent);
                    parent.Children.Add(node);
                    _currentNode = node;
                }

                NextToken();
                AnalyzeSimpleCommand();
            }

            _codeGenerator.GenerateLabel(secondLabel);
        }
        private void AnalyzeSimpleCommand(bool isFunction = false)
        {
            if (_token.Symbol == Symbols.SIdentificador)
            {
                var item = _symbolTable.Search(_token.Lexeme);

                if (item == null)
                {
                    RaiseNotFoundIdentificatorError(_token.Lexeme);
                }

                _analyzingLexeme = _token.Lexeme;

                var funcItem = item as FunctionItem;

                if (_funcInfo != null && funcItem?.Lexeme == _funcInfo.Name)
                {
                    NextToken();

                    if (_token.Symbol == Symbols.SAtribuicao)
                    {
                        AnalyzeAttribution();
                    }
                    else
                    {
                        throw new CompilationException(string.Format(WrongFunctionCall, _lexical.Position.Line, _lexical.Position.Column));
                    }

                    if (isFunction)
                    {
                        _currentNode = _rootNode;
                    }

                    if (_currentNode != null)
                    {
                        _currentNode.Children.Add(new SyntaxTreeNode
                        {
                            Parent = _currentNode,
                            Value = Symbols.SRetorno
                        });
                    }

                    _codeGenerator.GenerateInstruction(RETURNF, _funcInfo.FirstVarAddress, _funcInfo.VarsCount);
                }
                else
                {
                    NextToken();

                    if (_token.Symbol == Symbols.SAtribuicao)
                    {
                        AnalyzeAttribution();
                    }
                    else
                    {
                        AnalyzeProcCall();
                    }
                }
            }
            else if (_token.Symbol == Symbols.SSe)
            {
                AnalyzeIf();
            }
            else if (_token.Symbol == Symbols.SEnquanto)
            {
                AnalyzeWhile();
            }
            else if (_token.Symbol == Symbols.SLeia)
            {
                AnalyzeRead();
            }
            else if (_token.Symbol == Symbols.SEscreva)
            {
                AnalyzeWrite();
            }
            else
            {
                AnalyzeCommands();
            }
        }
        private void AnalyzeCommands(bool isFunction = false)
        {
            if (_token.Symbol == Symbols.SInicio)
            {
                NextToken();
                AnalyzeSimpleCommand(isFunction);

                while (_token.Symbol != Symbols.SFim)
                {
                    if (_token.Symbol == Symbols.SPontoVirgula)
                    {

                        if (_funcInfo != null)
                        {
                            _currentNode = _currentNode?.Parent ?? _rootNode;
                        }

                        NextToken();

                        if (_token.Symbol != Symbols.SFim)
                        {
                            AnalyzeSimpleCommand(isFunction);
                        }
                    }
                    else
                    {
                        RaiseMissingSemicolonError();
                    }
                }

                NextToken();
            }
            else
            {
                RaiseInvalidToken();
            }
        }
        private void AnalyzeBlock(bool isFunction = false)
        {
            uint totalVars;

            NextToken();
            totalVars = AnalyzeVarsDcl();

            if (totalVars > 0)
            {
                if (isFunction)
                {
                    _funcInfo.VarsCount = totalVars;
                    _funcInfo.FirstVarAddress = totalVars == 0 ? 0 : _allocBase;
                }

                _codeGenerator.GenerateInstruction(ALLOC, _allocBase, totalVars);
                _allocBase += totalVars;
            }

            _lastLabel++;

            if (isFunction)
            {
                //Saves the current values
                //We'll need this values saved in case a function has other functions inside it
                var rootNode = _rootNode;
                var funcInfo = _funcInfo;
                var currentNode = _currentNode;

                AnalyzeSubRoutines();

                _rootNode = rootNode;
                _funcInfo = funcInfo;
                _currentNode = currentNode;
            }
            else
            {
                AnalyzeSubRoutines();
            }

            AnalyzeCommands(true);
            
            if (totalVars > 0)
            {
                _allocBase -= totalVars;

                if (!isFunction)
                {
                    _codeGenerator.GenerateInstruction(DALLOC, _allocBase, totalVars);
                }

                _memory -= totalVars;
            }
        }