예제 #1
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>
        private HoconValue ParseValue(IHoconElement owner)
        {
            // value is lazy initialized because we don't know what kind of value we're parsing
            HoconValue value   = null;
            var        parsing = true;

            while (parsing)
            {
                switch (_tokens.Current.Type)
                {
                case TokenType.Include:
                    var includeToken = _tokens.Current;
                    var includeValue = ParseInclude();
                    switch (includeValue.Type)
                    {
                    case HoconType.Empty:
                        value = new HoconEmptyValue(owner);
                        break;

                    case HoconType.Object:
                        value = GetHoconValueFromParentElement(owner, TokenType.StartOfObject);
                        value.ReParent(includeValue);
                        break;

                    case HoconType.Array:
                        value = GetHoconValueFromParentElement(owner, TokenType.StartOfArray);
                        value.ReParent(includeValue);
                        break;

                    default:
                        throw HoconParserException.Create(includeToken, Path,
                                                          "Include could never contain a literal type.");
                    }

                    break;

                case TokenType.LiteralValue:
                    // Consume leading whitespaces.
                    if (_tokens.Current.IsNonSignificant())
                    {
                        _tokens.ToNextSignificant();
                    }

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

                    if (value == null)
                    {
                        value = GetHoconValueFromParentElement(owner, _tokens.Current.Type);
                    }

                    while (_tokens.Current.Type == TokenType.LiteralValue)
                    {
                        value.Add(HoconLiteral.Create(value, _tokens.Current));
                        _tokens.Next();
                    }

                    break;

                case TokenType.StartOfObject:
                    if (value == null)
                    {
                        value = GetHoconValueFromParentElement(owner, _tokens.Current.Type);
                    }

                    ParseObject(ref value);
                    break;

                case TokenType.StartOfArray:
                    if (value == null)
                    {
                        value = GetHoconValueFromParentElement(owner, _tokens.Current.Type);
                    }

                    // If this array is already initialized, we are going to overwrite it
                    if (value.Type == HoconType.Array && value.Count > 0)
                    {
                        value.Clear();
                    }

                    value.Add(ParseArray(value));
                    break;

                case TokenType.SubstituteOptional:
                case TokenType.SubstituteRequired:
                    if (value == null)
                    {
                        value = new HoconValue(owner);
                    }

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

                case TokenType.PlusEqualAssign:
                    if (value == null)
                    {
                        value = new HoconValue(owner);
                    }

                    var subAssign = new HoconSubstitution(value, new HoconPath(Path), _tokens.Current, false);
                    _substitutions.Add(subAssign);
                    value.Add(subAssign);
                    value.Add(ParsePlusEqualAssignArray(value));
                    parsing = false;
                    break;

                case TokenType.EndOfObject:
                case TokenType.EndOfArray:
                    parsing = false;
                    break;

                case TokenType.Comment:
                    _tokens.ToNextSignificant();
                    break;

                case TokenType.EndOfLine:
                    parsing = false;
                    break;

                case TokenType.EndOfFile:
                case TokenType.Comma:
                    parsing = false;
                    break;

                case TokenType.Assign:
                    // Special case to support end of line after assign
                    _tokens.ToNextSignificantLine();
                    break;

                default:
                    throw HoconParserException.Create(_tokens.Current, Path,
                                                      $"Failed to parse Hocon value. Unexpected token: `{_tokens.Current.Type}`");
                }
            }

            if (value == null)
            {
                value = new HoconEmptyValue(owner);
            }

            // trim trailing whitespace if result is a literal
            if (value.Type.IsLiteral())
            {
                if (value[value.Count - 1] is HoconWhitespace)
                {
                    value.RemoveAt(value.Count - 1);
                }
            }
            return(value);
        }
예제 #2
0
파일: Parser.cs 프로젝트: nagytech/HOCON
        /// <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>
        private HoconValue ParseValue(IHoconElement owner)
        {
            var value   = new HoconValue(owner);
            var parsing = true;

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

                case TokenType.LiteralValue:
                    // Consume leading whitespaces.
                    if (_tokens.Current.IsNonSignificant())
                    {
                        ConsumeWhitespace();
                    }
                    if (_tokens.Current.Type != TokenType.LiteralValue)
                    {
                        break;
                    }

                    while (_tokens.Current.Type == TokenType.LiteralValue)
                    {
                        value.Add(HoconLiteral.Create(value, _tokens.Current));
                        _tokens.Next();
                    }
                    break;

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

                case TokenType.StartOfArray:
                    value.Add(ParseArray(value));
                    break;

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

                case TokenType.EndOfObject:
                case TokenType.EndOfArray:
                    parsing = false;
                    break;

                // comments automatically stop value parsing.
                case TokenType.Comment:
                    ConsumeWhitelines();
                    parsing = false;
                    break;

                case TokenType.EndOfLine:
                    parsing = false;
                    break;

                case TokenType.EndOfFile:
                case TokenType.Comma:
                    parsing = false;
                    break;

                case TokenType.PlusEqualAssign:
                    HoconSubstitution subAssign = new HoconSubstitution(value, new HoconPath(Path), _tokens.Current, false);
                    _substitutions.Add(subAssign);
                    value.Add(subAssign);

                    value.Add(ParsePlusEqualAssignArray(value));
                    parsing = false;
                    break;

                case TokenType.Assign:
                    ConsumeWhitelines();
                    break;

                default:
                    throw HoconParserException.Create(_tokens.Current, Path,
                                                      $"Failed to parse Hocon value. Unexpected token: `{_tokens.Current.Type}`");
                }
            }

            // trim trailing whitespace if result is a literal
            if (value.Type == HoconType.Literal)
            {
                if (value[value.Count - 1] is HoconWhitespace)
                {
                    value.RemoveAt(value.Count - 1);
                }
            }
            return(value);
        }