Beispiel #1
0
        public IHoconElement Clone(IHoconElement newParent)
        {
            var clone = new HoconArray(newParent);

            clone.AddRange(this);
            return(clone);
        }
Beispiel #2
0
        private HoconArray ParsePlusEqualAssignArray(IHoconElement owner)
        {
            // sanity check
            if (_tokens.Current.Type != TokenType.PlusEqualAssign)
            {
                throw HoconParserException.Create(_tokens.Current, Path,
                                                  "Failed to parse Hocon field with += operator. " +
                                                  $"Expected {TokenType.PlusEqualAssign}, found {{_tokens.Current.Type}} instead.");
            }

            var currentArray = new HoconArray(owner);

            // consume += operator token
            ConsumeWhitelines();

            switch (_tokens.Current.Type)
            {
            case TokenType.Include:
                currentArray.Add(ParseInclude(currentArray));
                break;

            case TokenType.StartOfArray:
                // Array inside of arrays are parsed as values because it can be value concatenated with another array.
                currentArray.Add(ParseValue(currentArray));
                break;

            case TokenType.StartOfObject:
                currentArray.Add(ParseObject(currentArray));
                break;

            case TokenType.LiteralValue:
                if (_tokens.Current.IsNonSignificant())
                {
                    ConsumeWhitelines();
                }
                if (_tokens.Current.Type != TokenType.LiteralValue)
                {
                    break;
                }

                currentArray.Add(ParseValue(currentArray));
                break;

            case TokenType.SubstituteOptional:
            case TokenType.SubstituteRequired:
                var pointerPath       = HoconPath.Parse(_tokens.Current.Value);
                HoconSubstitution sub = new HoconSubstitution(currentArray, pointerPath, _tokens.Current,
                                                              _tokens.Current.Type == TokenType.SubstituteRequired);
                _substitutions.Add(sub);
                currentArray.Add(sub);
                _tokens.Next();
                break;

            default:
                throw HoconParserException.Create(_tokens.Current, Path,
                                                  $"Failed to parse Hocon array. Expected {TokenType.EndOfArray} but found {_tokens.Current.Type} instead.");
            }

            return(currentArray);
        }
Beispiel #3
0
        internal void ResolveValue(HoconSubstitution child)
        {
            var index = IndexOf(child);

            Remove(child);

            if (child.Type != HoconType.Empty)
            {
                if (Type == HoconType.Empty)
                {
                    Type = child.Type;
                }
                else if (!Type.IsMergeable(child.Type))
                {
                    throw HoconParserException.Create(child, child.Path,
                                                      "Invalid substitution, substituted type be must be mergeable with its sibling type. " +
                                                      $"Sibling type:{Type}, substitution type:{child.Type}");
                }

                var clonedValue = (HoconValue)child.ResolvedValue.Clone(Parent);
                switch (Type)
                {
                case HoconType.Object:
                    Insert(index, clonedValue.GetObject());
                    break;

                case HoconType.Array:
                    var hoconArray = new HoconArray(this);
                    hoconArray.AddRange(clonedValue.GetArray());
                    Insert(index, hoconArray);
                    break;

                case HoconType.Boolean:
                case HoconType.Number:
                case HoconType.String:
                    var elementList = new List <IHoconElement>();
                    foreach (var element in clonedValue)
                    {
                        elementList.Add(element);
                    }
                    InsertRange(index, elementList);
                    break;
                }
            }

            switch (Parent)
            {
            case HoconField v:
                v.ResolveValue(this);
                break;

            case HoconArray a:
                a.ResolveValue(child);
                break;

            default:
                throw new Exception($"Invalid parent type while resolving substitution:{Parent.GetType()}");
            }
        }
Beispiel #4
0
        private static void Flatten(IHoconElement node)
        {
            if (!(node is HoconValue v))
            {
                return;
            }

            switch (v.Type)
            {
            case HoconType.Object:
                var o = v.GetObject();
                v.Clear();
                v.Add(o);
                foreach (var item in o.Values)
                {
                    Flatten(item);
                }
                break;

            case HoconType.Array:
                var a = v.GetArray();
                v.Clear();
                var newArray = new HoconArray(v);
                foreach (var item in a)
                {
                    Flatten(item);
                    newArray.Add(item);
                }
                v.Add(newArray);
                break;

            case HoconType.Literal:
                if (v.Count == 1)
                {
                    return;
                }

                var value = v.GetString();
                v.Clear();
                if (value == null)
                {
                    v.Add(new HoconNull(v));
                }
                else if (value.NeedTripleQuotes())
                {
                    v.Add(new HoconTripleQuotedString(v, value));
                }
                else if (value.NeedQuotes())
                {
                    v.Add(new HoconQuotedString(v, value));
                }
                else
                {
                    v.Add(new HoconUnquotedString(v, value));
                }
                break;
            }
        }
Beispiel #5
0
        public IHoconElement Clone(IHoconElement newParent)
        {
            var newArray = new HoconArray(newParent);

            foreach (var value in this)
            {
                newArray.Add(value.Clone(newArray) as HoconValue);
            }
            return(newArray);
        }
Beispiel #6
0
 private bool Equals(HoconArray other)
 {
     if (Count != other.Count)
     {
         return(false);
     }
     for (var i = 0; i < Count; ++i)
     {
         if (!Equals(this[i], other[i]))
         {
             return(false);
         }
     }
     return(true);
 }
Beispiel #7
0
        /// <summary>
        /// Retrieves the next array token from the tokenizer.
        /// </summary>
        /// <returns>An array of elements retrieved from the token.</returns>
        public HoconArray ParseArray(string currentPath)
        {
            try
            {
                PushDiagnostics("[");

                var arr = new HoconArray();
                while (!_reader.EoF && !_reader.IsArrayEnd())
                {
                    var v = new HoconValue();
                    ParseValue(v, currentPath);
                    arr.Add(v);
                    _reader.PullWhitespaceAndComments();
                }
                _reader.PullArrayEnd();
                return(arr);
            }
            finally
            {
                PopDiagnostics();
            }
        }
Beispiel #8
0
        /// <summary>
        ///     Retrieves the next array token from the tokenizer.
        /// </summary>
        /// <returns>An array of elements retrieved from the token.</returns>
        private HoconArray ParseArray(IHoconElement owner)
        {
            // sanity check
            if (_tokens.Current.Type != TokenType.StartOfArray)
            {
                throw HoconParserException.Create(_tokens.Current, Path,
                                                  "Failed to parse Hocon array. " +
                                                  $"Expected {TokenType.StartOfArray}, found {_tokens.Current.Type} instead.");
            }

            var currentArray = new HoconArray(owner);

            // consume start of array token
            _tokens.ToNextSignificant();

            var valueWasParsed = false;
            var parsing        = true;

            while (parsing)
            {
                switch (_tokens.Current.Type)
                {
                case TokenType.Include:
                    if (valueWasParsed)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    currentArray.Add(ParseValue(currentArray));
                    valueWasParsed = true;
                    break;

                case TokenType.LiteralValue:
                    if (_tokens.Current.IsNonSignificant())
                    {
                        _tokens.ToNextSignificant();
                    }

                    if (_tokens.Current.Type != TokenType.LiteralValue)
                    {
                        break;
                    }

                    if (valueWasParsed)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    currentArray.Add(ParseValue(currentArray));
                    valueWasParsed = true;
                    break;

                case TokenType.StartOfObject:
                    if (valueWasParsed)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    currentArray.Add(ParseValue(currentArray));
                    valueWasParsed = true;
                    break;

                case TokenType.StartOfArray:
                    if (valueWasParsed)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    // Array inside of arrays are parsed as values because it can be value concatenated with another array.
                    currentArray.Add(ParseValue(currentArray));
                    valueWasParsed = true;
                    break;

                case TokenType.SubstituteOptional:
                case TokenType.SubstituteRequired:
                    if (valueWasParsed)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    currentArray.Add(ParseValue(currentArray));
                    valueWasParsed = true;
                    break;

                case TokenType.EndOfArray:
                    valueWasParsed = false;

                    // If there is a next array on the same like - let's move to it's first element
                    if (_tokens.ForwardMatch(TokenType.StartOfArray))
                    {
                        _tokens.ToNextSignificant();
                        _tokens.Next();
                    }
                    else
                    {
                        // Otherwise, array value is fully loaded and nothing to do here
                        parsing = false;
                    }

                    break;

                case TokenType.Comment:
                case TokenType.EndOfLine:
                    valueWasParsed = false;
                    _tokens.ToNextSignificantLine();
                    break;

                case TokenType.Comma:
                    if (!valueWasParsed)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected a valid value, found `{_tokens.Current.Type}` instead.");
                    }

                    valueWasParsed = false;
                    _tokens.ToNextSignificant();
                    break;

                default:
                    throw HoconParserException.Create(_tokens.Current, Path,
                                                      $"Failed to parse Hocon array. Expected {TokenType.EndOfArray} but found {_tokens.Current.Type} instead.");
                }
            }

            // Consume end of array token
            _tokens.Next();
            return(currentArray);
        }
Beispiel #9
0
        private HoconArray ParsePlusEqualAssignArray(IHoconElement owner)
        {
            // sanity check
            if (_tokens.Current.Type != TokenType.PlusEqualAssign)
            {
                throw HoconParserException.Create(_tokens.Current, Path,
                                                  "Failed to parse Hocon field with += operator. " +
                                                  $"Expected {TokenType.PlusEqualAssign}, found {_tokens.Current.Type} instead.");
            }

            var currentArray = new HoconArray(owner);

            // consume += operator token
            _tokens.ToNextSignificant();

            switch (_tokens.Current.Type)
            {
            case TokenType.Include:
                var includeToken = _tokens.Current;
                var includeValue = ParseInclude();
                if (includeValue.Type == HoconType.Empty)
                {
                    break;
                }

                if (currentArray.Type != HoconType.Empty && currentArray.Type != includeValue.Type)
                {
                    throw HoconParserException.Create(includeToken, Path,
                                                      "Invalid Hocon include. Hocon config substitution type must be the same as the field it's merged into. " +
                                                      $"Expected type: `{currentArray.Type}`, type returned by include callback: `{includeValue.Type}`");
                }

                currentArray.Add((HoconValue)includeValue.Clone(currentArray));
                break;

            case TokenType.StartOfArray:
                // Array inside of arrays are parsed as values because it can be value concatenated with another array.
                currentArray.Add(ParseValue(currentArray));
                break;

            case TokenType.StartOfObject:
                currentArray.Add(ParseValue(currentArray));
                break;

            case TokenType.LiteralValue:
                if (_tokens.Current.IsNonSignificant())
                {
                    _tokens.ToNextSignificant();
                }

                if (_tokens.Current.Type != TokenType.LiteralValue)
                {
                    break;
                }

                currentArray.Add(ParseValue(currentArray));
                break;

            case TokenType.SubstituteOptional:
            case TokenType.SubstituteRequired:
                currentArray.Add(ParseValue(currentArray));
                break;

            default:
                throw HoconParserException.Create(_tokens.Current, Path,
                                                  $"Failed to parse Hocon array. Expected {TokenType.EndOfArray} but found {_tokens.Current.Type} instead.");
            }

            return(currentArray);
        }
Beispiel #10
0
        /// <summary>
        /// Retrieves the next value token from the tokenizer and appends it
        /// to the supplied element <paramref name="owner"/>.
        /// </summary>
        /// <param name="owner">The element to append the next token.</param>
        /// <exception cref="System.Exception">End of file reached while trying to read a value</exception>
        public void ParseValue(HoconValue owner, string currentPath)
        {
            if (_reader.EoF)
            {
                throw new HoconParserException("End of file reached while trying to read a value");
            }

            _reader.PullWhitespaceAndComments();
            var start = _reader.Index;

            try
            {
                while (_reader.IsValue())
                {
                    Token t = _reader.PullValue();

                    switch (t.Type)
                    {
                    case TokenType.EoF:
                        break;

                    case TokenType.LiteralValue:
                        if (owner.IsObject())
                        {
                            //needed to allow for override objects
                            owner.Clear();
                        }
                        var lit = new HoconLiteral
                        {
                            Value = t.Value
                        };
                        owner.AppendValue(lit);

                        break;

                    case TokenType.ObjectStart:
                        ParseObject(owner, true, currentPath);
                        break;

                    case TokenType.ArrayStart:
                        HoconArray arr = ParseArray(currentPath);
                        owner.AppendValue(arr);
                        break;

                    case TokenType.Substitute:
                        HoconSubstitution sub = ParseSubstitution(t.Value);
                        _substitutions.Add(sub);
                        owner.AppendValue(sub);
                        break;
                    }
                    if (_reader.IsSpaceOrTab())
                    {
                        ParseTrailingWhitespace(owner);
                    }
                }

                IgnoreComma();
            }
            catch (HoconTokenizerException tokenizerException)
            {
                throw new HoconParserException(string.Format("{0}\r{1}", tokenizerException.Message, GetDiagnosticsStackTrace()), tokenizerException);
            }
            finally
            {
                //no value was found, tokenizer is still at the same position
                if (_reader.Index == start)
                {
                    throw new HoconParserException(string.Format("Hocon syntax error {0}\r{1}", _reader.GetHelpTextAtIndex(start), GetDiagnosticsStackTrace()));
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Retrieves the next array token from the tokenizer.
        /// </summary>
        /// <returns>An array of elements retrieved from the token.</returns>
        private HoconArray ParseArray(IHoconElement owner)
        {
            var currentArray = new HoconArray(owner);

            // consume start of array token
            ConsumeWhitelines();

            IHoconElement lastValue = null;
            var           parsing   = true;

            while (parsing)
            {
                switch (_tokens.Current.Type)
                {
                case TokenType.Include:
                    if (lastValue != null)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    lastValue = ParseInclude(currentArray);
                    break;

                case TokenType.StartOfArray:
                    if (lastValue != null)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    // Array inside of arrays are parsed as values because it can be value concatenated with another array.
                    lastValue = ParseValue(currentArray);
                    break;

                case TokenType.StartOfObject:
                    if (lastValue != null)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    lastValue = ParseObject(currentArray);
                    break;

                case TokenType.LiteralValue:
                    if (_tokens.Current.IsNonSignificant())
                    {
                        ConsumeWhitelines();
                    }
                    if (_tokens.Current.Type != TokenType.LiteralValue)
                    {
                        break;
                    }

                    if (lastValue != null)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    lastValue = ParseValue(currentArray);
                    break;

                case TokenType.SubstituteOptional:
                case TokenType.SubstituteRequired:
                    if (lastValue != null)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected `{TokenType.Comma}` or `{TokenType.EndOfLine}, " +
                                                          $"found `{_tokens.Current.Type}` instead.");
                    }

                    var pointerPath       = HoconPath.Parse(_tokens.Current.Value);
                    HoconSubstitution sub = new HoconSubstitution(currentArray, pointerPath, _tokens.Current,
                                                                  _tokens.Current.Type == TokenType.SubstituteRequired);
                    _substitutions.Add(sub);
                    lastValue = sub;
                    _tokens.Next();
                    break;

                case TokenType.Comment:
                case TokenType.EndOfLine:
                    if (lastValue == null)
                    {
                        ConsumeWhitelines();
                        break;
                    }

                    switch (lastValue.Type)
                    {
                    case HoconType.Array:
                        currentArray.Add(lastValue);
                        break;

                    default:
                        currentArray.Add(lastValue);
                        break;
                    }
                    lastValue = null;
                    ConsumeWhitelines();
                    break;

                case TokenType.Comma:
                    if (lastValue == null)
                    {
                        throw HoconParserException.Create(_tokens.Current, Path,
                                                          $"Failed to parse Hocon array. Expected a valid value, found `{_tokens.Current.Type}` instead.");
                    }

                    switch (lastValue.Type)
                    {
                    case HoconType.Array:
                        currentArray.Add(lastValue);
                        break;

                    default:
                        currentArray.Add(lastValue);
                        break;
                    }
                    lastValue = null;
                    ConsumeWhitelines();
                    break;

                case TokenType.EndOfArray:
                    if (lastValue != null)
                    {
                        switch (lastValue.Type)
                        {
                        case HoconType.Array:
                            currentArray.Add(lastValue);
                            break;

                        default:
                            currentArray.Add(lastValue);
                            break;
                        }
                        lastValue = null;
                    }
                    parsing = false;
                    break;

                default:
                    throw HoconParserException.Create(_tokens.Current, Path,
                                                      $"Failed to parse Hocon array. Expected {TokenType.EndOfArray} but found {_tokens.Current.Type} instead.");
                }
            }

            // Consume end of array token
            _tokens.Next();
            return(currentArray);
        }