private void ParseTrailingWhitespace(HoconValue owner) { Token ws = _reader.PullSpaceOrTab(); //single line ws should be included if string concat if (ws.Value.Length > 0) { var wsLit = new HoconLiteral { Value = ws.Value, }; owner.AppendValue(wsLit); } }
/// <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); }
/// <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())); } } }
/// <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); }