private static PSObject PopulateConfonObject(ConfonValue jv, ConfonContext context, string path, out ErrorRecord error)
        {
            if (jv == null)
                throw new ArgumentNullException(nameof(jv));

            error = null;

            if (!jv.IsObject())
                throw new ArgumentException("Internal error: Non-container object has entered `PopulateConfonObject`.");

            PSObject psObject = new PSObject();
            ConfonObject confonObject = jv.GetObject();

            foreach (string key in confonObject.Items.Keys)
            {
                ConfonValue child = confonObject.Items[key];

                // escape quotes in key
                string safeKey = key;
                if (key.Contains(".") || key.Contains("[") || key.Contains("]"))
                    safeKey = "'" + key.Replace("'", "\\'") + "'";

                string childPath = (path == null) 
                    ? safeKey 
                    : (path + "." + safeKey);

                if (child.IsEmpty)
                {
                    psObject.Properties.Add(new PSNoteProperty(key, null));
                }
                else if (child.IsString())
                {
                    // populate a leaf
                    psObject.Properties.Add(new PSNoteProperty(key, PopulateConfonLeaf(child, childPath, out error)));
                }
                else if (child.IsObject())
                {
                    // populate an object. recurse!
                    psObject.Properties.Add(new PSNoteProperty(key, PopulateConfonObject(child, context, childPath, out error)));
                }
                else if (child.IsArray())
                {
                    // quote the safeKey

                    psObject.Properties.Add(new PSNoteProperty(key, PopulateConfonArray(child, context, path, safeKey, out error)));
                }
                else
                {
                    error = new ErrorRecord(new NotImplementedException(string.Format("Unable to determine object type at {0}", childPath)), "UnhandledDataType", ErrorCategory.ParserError, null);
                }

                if (error != null)
                    return null;
            }

            return psObject;
        }
        private static object[] PopulateConfonArray(ConfonValue jv, ConfonContext context, string parentPath, string childName, out ErrorRecord error)
        {
            if (jv == null)
                throw new ArgumentNullException(nameof(jv));

            error = null;

            if (!jv.IsArray())
                throw new ArgumentException("Internal error: Non-array object has entered `PopulateConfonObject`.");

            IList<ConfonValue> values = jv.GetArray();
            List<object> results = new List<object>();

            int indexPosition = 0;
            foreach (ConfonValue current in values)
            {
                string indexedItemPath = string.Format("{0}.'{1}[{2}]'", parentPath, childName, indexPosition);

                if (current.IsEmpty)
                {
                    results.Add(null);
                }
                else if (current.IsString())
                {
                    results.Add(PopulateConfonLeaf(current, indexedItemPath, out error));
                }
                else if (current.IsObject())
                {
                    results.Add(PopulateConfonObject(current, context, indexedItemPath, out error));
                }
                else if (current.IsArray())
                {
                    // array in array...
                    results.Add(PopulateConfonArray(current, context, parentPath, indexPosition.ToString(), out error));
                }
                else
                {
                    error = new ErrorRecord(new NotImplementedException(string.Format("Unable to determine object type at {0}", indexedItemPath)), "UnhandledDataType", ErrorCategory.ParserError, null);
                }

                if (error != null)
                    return null;

                indexPosition += 1;
            }

            return results.ToArray();
        }
        private static object TransverseConfonRoot(ConfonContext context, out ErrorRecord error)
        {
            // internal exception catching
            if (context == null)
                throw new ArgumentNullException(nameof(context));

            error = null;

            if (context.IsEmpty)
                return null;

            if (!context.Root.IsObject())
            {
                error = new ErrorRecord(new FormatException(RS.Err_BsdRootNotAnObject), "BsdRootNotAnObject", ErrorCategory.ParserError, null);
                return null;
            }

            return PopulateConfonObject(context.Root, context, null, out error);
        }
        protected override void EndProcessing()
        {
            // ignore empty entry
            if (_inputObjectBuffer.Count == 0)
                return;

            // It is not actually easy to write syntaxically wrong Confon.
            // So instead of trying to figure out if it is a list of bsd or 
            // just newlines, let's just join the list to a whole big string.

            ConfonContext context;
            ConfonContext userContext;
            try
            {
                if (_inputObjectBuffer.Count == 1)
                    userContext = ConfonFactory.ParseString(string.Join(Environment.NewLine, _inputObjectBuffer[0]));
                else
                    userContext = ConfonFactory.ParseString(string.Join(Environment.NewLine, _inputObjectBuffer.ToArray()));

                if (_fallback == null || _fallback.Length == 0)
                {
                    context = userContext;
                }
                else if (_fallback.Length == 1)
                {
                    if (string.IsNullOrEmpty(_fallback[0]))
                        context = userContext;
                    else
                        context = userContext.WithFallback(ConfonFactory.ParseString(_fallback[0]));
                }
                else
                {
                    ConfonContext baseContext = null;
                    for (int i = _fallback.Length - 1; i >= 0; i--)
                    {
                        if (string.IsNullOrEmpty(_fallback[i]))
                            continue;

                        if (baseContext == null)
                            baseContext = ConfonFactory.ParseString(_fallback[i]);       
                        else
                            baseContext = baseContext.WithFallback(ConfonFactory.ParseString(_fallback[i]));
                    }

                    if (baseContext == null)
                        context = userContext;
                    else
                        context = userContext.WithFallback(baseContext);
                }

                // Handle empty situation
                if (context.IsEmpty)
                    return;

                ErrorRecord populateError;
                object obj = TransverseConfonRoot(context, out populateError);
                if (populateError != null)
                    base.ThrowTerminatingError(populateError);

                base.WriteObject(obj);
            }
            catch (Exception ex)
            {
                ErrorRecord errorRecord = new ErrorRecord(ex, "BsdConversionFailure", ErrorCategory.ParserError, null);
                base.ThrowTerminatingError(errorRecord);
            }
        }