public static TypeNode Parse(Parser.State state)
        {
            state.Save();
            TypeNode type = new TypeNode();

            while (true)
            {
                var tok = state.GetToken();
                if (tok.Is(TokenType.Identifier, "const"))
                {
                    if (type.IsConstant)
                    {
                        state.ErrorCode    = (uint)ErrorCodes.P_DuplicatedModifier;
                        state.ErrorMessage =
                            "<const> type modifier can not be used twice" +
                            " for the same type";
                        return(null);
                    }

                    type.IsConstant = true;
                }
                else if (tok.Is(TokenType.Identifier, "ref"))
                {
                    state.GetNextNEToken();
                    type.IsReference   = true;
                    type.ReferenceType = Parse(state);

                    if (type.IsConstant)
                    {
                        state.ErrorCode    = (uint)ErrorCodes.P_ReferenceCanNotBeConstant;
                        state.ErrorMessage =
                            "Reference can not have a constant modifier:\n" +
                            type.ToString();
                    }

                    return(type);
                }
                else if (tok.Is(TokenSubType.BraceSquareLeft, "["))
                {
                    state.GetNextNEToken();
                    type.IsArrayType = true;

                    // TODO: Parse sizes
                    if (!state.GetToken().Is(TokenSubType.BraceSquareRight, "]"))
                    {
                        state.ErrorCode    = 999;
                        state.ErrorMessage =
                            "Array does not support sizes and dimmensions " +
                            "in the current version";
                        return(type);
                    }
                    state.GetNextNEToken();

                    type.ReferenceType = Parse(state);

                    if (type.ReferenceType.IsReference)
                    {
                        state.ErrorCode    = (uint)ErrorCodes.P_ArrayCanNotContainReferences;
                        state.ErrorMessage =
                            "Array can not consist of references";
                    }

                    return(type);
                }
                else
                {
                    // End of modifiers
                    break;
                }

                state.GetNextNEToken();
            }

            type.TypePath = ParsePath(state);
            return(type);
        }
        private static bool ParseFunctionDeclaration(Parser.State state, CoreNode coreNode)
        {
            state.Save();

            if (state.GetToken().Type != TokenType.Identifier)
            {
                state.Restore();
                return(false);
            }

            string name = state.GetTokenAndMoveNE().Value;

            if (!state.GetToken().Is(TokenSubType.Colon, ":"))
            {
                state.ErrorCode    = (uint)ErrorCodes.P_ColonBeforeTypeSpeceficationNotFound;
                state.ErrorMessage =
                    $"Expected <Colon>(:) before function type specification " +
                    $"but <{state.GetToken().SubType}>({state.GetToken().Value}) were given";
                return(false);
            }
            state.GetNextNEToken();

            TypeNode type = TypeParser.Parse(state);

            if (state.IsErrorOccured())
            {
                return(false);
            }

            /*
             * // Only for class methods
             * bool isInstance = state.GetToken().Is(TokenSubType.Dot, ".");
             * bool isStatic = state.GetToken().Is(TokenSubType.Colon, ":");
             *
             * if (!(isStatic || isInstance))
             * {
             *  state.ErrorCode = (uint)ErrorCodes.P_MethodTypeExpected;
             *  state.ErrorMessage =
             *      $"Expected '.' or ':' as type modifier, but " +
             *      $"<{state.GetToken().SubType.ToString()}> were found";
             *  return false;
             * }
             */

            FunctionNode function = new FunctionNode
            {
                Parent = coreNode,
                Name   = name,
                Type   = FunctionNode.EType.Static,

                ReturnType = type
            };

            coreNode.FunctionNodes.Add(function);

            if (!state.GetToken().Is(TokenSubType.BraceRoundLeft, "("))
            {
                state.ErrorCode    = (uint)ErrorCodes.P_OpeningBracketExpected;
                state.ErrorMessage =
                    $"Opening round bracket is expected before parameters list " +
                    $"but <{state.GetToken().SubType}> were given";

                return(false);
            }

            state.GetNextNEToken();
            FunctionParser.ParseParametersList(state, function);
            if (state.IsErrorOccured())
            {
                return(true);
            }

            // FunctionParser.ParseTemplateValues(state, function);
            function.Code = CodeParser.Parse(state);
            return(!state.IsErrorOccured());
        }