X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FYAMLParser.cpp;h=bb02bbbc5b46987650168abf733a51a4b2299bd2;hb=3808efa2e6e2da057c29c4fdc4ef083a244f9371;hp=9e506128bc2b52cb596feb2129b07b83c2db9873;hpb=8fc9986bdf710b6e1e4a2d4371e563749c38ba4d;p=oota-llvm.git diff --git a/lib/Support/YAMLParser.cpp b/lib/Support/YAMLParser.cpp index 9e506128bc2..bb02bbbc5b4 100644 --- a/lib/Support/YAMLParser.cpp +++ b/lib/Support/YAMLParser.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/YAMLParser.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" @@ -96,6 +97,16 @@ static EncodingInfo getUnicodeEncoding(StringRef Input) { namespace llvm { namespace yaml { +/// Pin the vtables to this file. +void Node::anchor() {} +void NullNode::anchor() {} +void ScalarNode::anchor() {} +void BlockScalarNode::anchor() {} +void KeyValueNode::anchor() {} +void MappingNode::anchor() {} +void SequenceNode::anchor() {} +void AliasNode::anchor() {} + /// Token - A single YAML token. struct Token : ilist_node { enum TokenKind { @@ -118,6 +129,7 @@ struct Token : ilist_node { TK_Key, TK_Value, TK_Scalar, + TK_BlockScalar, TK_Alias, TK_Anchor, TK_Tag @@ -127,6 +139,9 @@ struct Token : ilist_node { /// of the token in the input. StringRef Range; + /// The value of a block scalar node. + std::string Value; + Token() : Kind(TK_Error) {} }; } @@ -153,7 +168,7 @@ struct ilist_node_traits { Token *createNode(const Token &V) { return new (Alloc.Allocate()) Token(V); } - static void deleteNode(Token *V) {} + static void deleteNode(Token *V) { V->~Token(); } void addNodeToList(Token *) {} void removeNodeFromList(Token *) {} @@ -250,8 +265,8 @@ namespace yaml { /// @brief Scans YAML tokens from a MemoryBuffer. class Scanner { public: - Scanner(const StringRef Input, SourceMgr &SM); - Scanner(MemoryBuffer *Buffer, SourceMgr &SM_); + Scanner(StringRef Input, SourceMgr &SM, bool ShowColors = true); + Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors = true); /// @brief Parse the next token and return it without popping it. Token &peekNext(); @@ -261,7 +276,7 @@ public: void printError(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Message, ArrayRef Ranges = None) { - SM.PrintMessage(Loc, Kind, Message, Ranges); + SM.PrintMessage(Loc, Kind, Message, Ranges, /* FixIts= */ None, ShowColors); } void setError(const Twine &Message, StringRef::iterator Position) { @@ -285,6 +300,8 @@ public: } private: + void init(MemoryBufferRef Buffer); + StringRef currentInput() { return StringRef(Current, End - Current); } @@ -336,6 +353,14 @@ private: /// b-break. StringRef::iterator skip_b_break(StringRef::iterator Position); + /// Skip a single s-space[31] starting at Position. + /// + /// An s-space is 0x20 + /// + /// @returns The code unit after the s-space, or Position if it's not a + /// s-space. + StringRef::iterator skip_s_space(StringRef::iterator Position); + /// @brief Skip a single s-white[33] starting at Position. /// /// A s-white is 0x20 | 0x9 @@ -361,6 +386,10 @@ private: StringRef::iterator skip_while( SkipWhileFunc Func , StringRef::iterator Position); + /// Skip minimal well-formed code unit subsequences until Func returns its + /// input. + void advanceWhile(SkipWhileFunc Func); + /// @brief Scan ns-uri-char[39]s starting at Cur. /// /// This updates Cur and Column while scanning. @@ -369,9 +398,6 @@ private: /// sequence of ns-uri-char. StringRef scan_ns_uri_char(); - /// @brief Scan ns-plain-one-line[133] starting at \a Cur. - StringRef scan_ns_plain_one_line(); - /// @brief Consume a minimal well-formed code unit subsequence starting at /// \a Cur. Return false if it is not the same Unicode scalar value as /// \a Expected. This updates \a Column. @@ -384,6 +410,11 @@ private: /// Pos is whitespace or a new line bool isBlankOrBreak(StringRef::iterator Position); + /// Consume a single b-break[28] if it's present at the current position. + /// + /// Return false if the code unit at the current position isn't a line break. + bool consumeLineBreakIfPresent(); + /// @brief If IsSimpleKeyAllowed, create and push_back a new SimpleKey. void saveSimpleKeyCandidate( TokenQueueT::iterator Tok , unsigned AtColumn @@ -408,6 +439,10 @@ private: , Token::TokenKind Kind , TokenQueueT::iterator InsertPoint); + /// @brief Skip a single-line comment when the comment starts at the current + /// position of the scanner. + void skipComment(); + /// @brief Skip whitespace and comments until the start of the next token. void scanToNextToken(); @@ -453,6 +488,30 @@ private: /// @brief Scan a block scalar starting with | or >. bool scanBlockScalar(bool IsLiteral); + /// Scan a chomping indicator in a block scalar header. + char scanBlockChompingIndicator(); + + /// Scan an indentation indicator in a block scalar header. + unsigned scanBlockIndentationIndicator(); + + /// Scan a block scalar header. + /// + /// Return false if an error occurred. + bool scanBlockScalarHeader(char &ChompingIndicator, unsigned &IndentIndicator, + bool &IsDone); + + /// Look for the indentation level of a block scalar. + /// + /// Return false if an error occurred. + bool findBlockScalarIndent(unsigned &BlockIndent, unsigned BlockExitIndent, + unsigned &LineBreaks, bool &IsDone); + + /// Scan the indentation of a text line in a block scalar. + /// + /// Return false if an error occurred. + bool scanBlockScalarIndent(unsigned BlockIndent, unsigned BlockExitIndent, + bool &IsDone); + /// @brief Scan a tag of the form !stuff. bool scanTag(); @@ -463,7 +522,7 @@ private: SourceMgr &SM; /// @brief The original input. - MemoryBuffer *InputBuffer; + MemoryBufferRef InputBuffer; /// @brief The current position of the scanner. StringRef::iterator Current; @@ -492,6 +551,9 @@ private: /// @brief True if an error has occurred. bool Failed; + /// @brief Should colors be used when printing out the diagnostic messages? + bool ShowColors; + /// @brief Queue of tokens. This is required to queue up tokens while looking /// for the end of a simple key. And for cases where a single character /// can produce multiple tokens (e.g. BlockEnd). @@ -596,6 +658,9 @@ bool yaml::dumpTokens(StringRef Input, raw_ostream &OS) { case Token::TK_Scalar: OS << "Scalar: "; break; + case Token::TK_BlockScalar: + OS << "Block Scalar: "; + break; case Token::TK_Alias: OS << "Alias: "; break; @@ -693,34 +758,30 @@ std::string yaml::escape(StringRef Input) { return EscapedInput; } -Scanner::Scanner(StringRef Input, SourceMgr &sm) - : SM(sm) - , Indent(-1) - , Column(0) - , Line(0) - , FlowLevel(0) - , IsStartOfStream(true) - , IsSimpleKeyAllowed(true) - , Failed(false) { - InputBuffer = MemoryBuffer::getMemBuffer(Input, "YAML"); - SM.AddNewSourceBuffer(InputBuffer, SMLoc()); - Current = InputBuffer->getBufferStart(); - End = InputBuffer->getBufferEnd(); -} - -Scanner::Scanner(MemoryBuffer *Buffer, SourceMgr &SM_) - : SM(SM_) - , InputBuffer(Buffer) - , Current(InputBuffer->getBufferStart()) - , End(InputBuffer->getBufferEnd()) - , Indent(-1) - , Column(0) - , Line(0) - , FlowLevel(0) - , IsStartOfStream(true) - , IsSimpleKeyAllowed(true) - , Failed(false) { - SM.AddNewSourceBuffer(InputBuffer, SMLoc()); +Scanner::Scanner(StringRef Input, SourceMgr &sm, bool ShowColors) + : SM(sm), ShowColors(ShowColors) { + init(MemoryBufferRef(Input, "YAML")); +} + +Scanner::Scanner(MemoryBufferRef Buffer, SourceMgr &SM_, bool ShowColors) + : SM(SM_), ShowColors(ShowColors) { + init(Buffer); +} + +void Scanner::init(MemoryBufferRef Buffer) { + InputBuffer = Buffer; + Current = InputBuffer.getBufferStart(); + End = InputBuffer.getBufferEnd(); + Indent = -1; + Column = 0; + Line = 0; + FlowLevel = 0; + IsStartOfStream = true; + IsSimpleKeyAllowed = true; + Failed = false; + std::unique_ptr InputBufferOwner = + MemoryBuffer::getMemBuffer(Buffer); + SM.AddNewSourceBuffer(std::move(InputBufferOwner), SMLoc()); } Token &Scanner::peekNext() { @@ -740,7 +801,7 @@ Token &Scanner::peekNext() { removeStaleSimpleKeyCandidates(); SimpleKey SK; - SK.Tok = TokenQueue.front(); + SK.Tok = TokenQueue.begin(); if (std::find(SimpleKeys.begin(), SimpleKeys.end(), SK) == SimpleKeys.end()) break; @@ -804,6 +865,13 @@ StringRef::iterator Scanner::skip_b_break(StringRef::iterator Position) { return Position; } +StringRef::iterator Scanner::skip_s_space(StringRef::iterator Position) { + if (Position == End) + return Position; + if (*Position == ' ') + return Position + 1; + return Position; +} StringRef::iterator Scanner::skip_s_white(StringRef::iterator Position) { if (Position == End) @@ -832,6 +900,12 @@ StringRef::iterator Scanner::skip_while( SkipWhileFunc Func return Position; } +void Scanner::advanceWhile(SkipWhileFunc Func) { + auto Final = skip_while(Func, Current); + Column += Final - Current; + Current = Final; +} + static bool is_ns_hex_digit(const char C) { return (C >= '0' && C <= '9') || (C >= 'a' && C <= 'z') @@ -864,42 +938,6 @@ StringRef Scanner::scan_ns_uri_char() { return StringRef(Start, Current - Start); } -StringRef Scanner::scan_ns_plain_one_line() { - StringRef::iterator start = Current; - // The first character must already be verified. - ++Current; - while (true) { - if (Current == End) { - break; - } else if (*Current == ':') { - // Check if the next character is a ns-char. - if (Current + 1 == End) - break; - StringRef::iterator i = skip_ns_char(Current + 1); - if (Current + 1 != i) { - Current = i; - Column += 2; // Consume both the ':' and ns-char. - } else - break; - } else if (*Current == '#') { - // Check if the previous character was a ns-char. - // The & 0x80 check is to check for the trailing byte of a utf-8 - if (*(Current - 1) & 0x80 || skip_ns_char(Current - 1) == Current) { - ++Current; - ++Column; - } else - break; - } else { - StringRef::iterator i = skip_nb_char(Current); - if (i == Current) - break; - Current = i; - ++Column; - } - } - return StringRef(start, Current - start); -} - bool Scanner::consume(uint32_t Expected) { if (Expected >= 0x80) report_fatal_error("Not dealing with this yet"); @@ -930,6 +968,16 @@ bool Scanner::isBlankOrBreak(StringRef::iterator Position) { return false; } +bool Scanner::consumeLineBreakIfPresent() { + auto Next = skip_b_break(Current); + if (Next == Current) + return false; + Column = 0; + ++Line; + Current = Next; + return true; +} + void Scanner::saveSimpleKeyCandidate( TokenQueueT::iterator Tok , unsigned AtColumn , bool IsRequired) { @@ -995,24 +1043,27 @@ bool Scanner::rollIndent( int ToColumn return true; } +void Scanner::skipComment() { + if (*Current != '#') + return; + while (true) { + // This may skip more than one byte, thus Column is only incremented + // for code points. + StringRef::iterator I = skip_nb_char(Current); + if (I == Current) + break; + Current = I; + ++Column; + } +} + void Scanner::scanToNextToken() { while (true) { while (*Current == ' ' || *Current == '\t') { skip(1); } - // Skip comment. - if (*Current == '#') { - while (true) { - // This may skip more than one byte, thus Column is only incremented - // for code points. - StringRef::iterator i = skip_nb_char(Current); - if (i == Current) - break; - Current = i; - ++Column; - } - } + skipComment(); // Skip EOL. StringRef::iterator i = skip_b_break(Current); @@ -1112,7 +1163,7 @@ bool Scanner::scanFlowCollectionStart(bool IsSequence) { TokenQueue.push_back(T); // [ and { may begin a simple key. - saveSimpleKeyCandidate(TokenQueue.back(), Column - 1, false); + saveSimpleKeyCandidate(--TokenQueue.end(), Column - 1, false); // And may also be followed by a simple key. IsSimpleKeyAllowed = true; @@ -1275,7 +1326,7 @@ bool Scanner::scanFlowScalar(bool IsDoubleQuoted) { T.Range = StringRef(Start, Current - Start); TokenQueue.push_back(T); - saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); + saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false); IsSimpleKeyAllowed = false; @@ -1353,7 +1404,7 @@ bool Scanner::scanPlainScalar() { TokenQueue.push_back(T); // Plain scalars can be simple keys. - saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); + saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false); IsSimpleKeyAllowed = false; @@ -1388,45 +1439,211 @@ bool Scanner::scanAliasOrAnchor(bool IsAlias) { TokenQueue.push_back(T); // Alias and anchors can be simple keys. - saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); + saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false); IsSimpleKeyAllowed = false; return true; } -bool Scanner::scanBlockScalar(bool IsLiteral) { - StringRef::iterator Start = Current; - skip(1); // Eat | or > - while(true) { - StringRef::iterator i = skip_nb_char(Current); - if (i == Current) { - if (Column == 0) - break; - i = skip_b_break(Current); - if (i != Current) { - // We got a line break. - Column = 0; - ++Line; - Current = i; - continue; - } else { - // There was an error, which should already have been printed out. +char Scanner::scanBlockChompingIndicator() { + char Indicator = ' '; + if (Current != End && (*Current == '+' || *Current == '-')) { + Indicator = *Current; + skip(1); + } + return Indicator; +} + +/// Get the number of line breaks after chomping. +/// +/// Return the number of trailing line breaks to emit, depending on +/// \p ChompingIndicator. +static unsigned getChompedLineBreaks(char ChompingIndicator, + unsigned LineBreaks, StringRef Str) { + if (ChompingIndicator == '-') // Strip all line breaks. + return 0; + if (ChompingIndicator == '+') // Keep all line breaks. + return LineBreaks; + // Clip trailing lines. + return Str.empty() ? 0 : 1; +} + +unsigned Scanner::scanBlockIndentationIndicator() { + unsigned Indent = 0; + if (Current != End && (*Current >= '1' && *Current <= '9')) { + Indent = unsigned(*Current - '0'); + skip(1); + } + return Indent; +} + +bool Scanner::scanBlockScalarHeader(char &ChompingIndicator, + unsigned &IndentIndicator, bool &IsDone) { + auto Start = Current; + + ChompingIndicator = scanBlockChompingIndicator(); + IndentIndicator = scanBlockIndentationIndicator(); + // Check for the chomping indicator once again. + if (ChompingIndicator == ' ') + ChompingIndicator = scanBlockChompingIndicator(); + Current = skip_while(&Scanner::skip_s_white, Current); + skipComment(); + + if (Current == End) { // EOF, we have an empty scalar. + Token T; + T.Kind = Token::TK_BlockScalar; + T.Range = StringRef(Start, Current - Start); + TokenQueue.push_back(T); + IsDone = true; + return true; + } + + if (!consumeLineBreakIfPresent()) { + setError("Expected a line break after block scalar header", Current); + return false; + } + return true; +} + +bool Scanner::findBlockScalarIndent(unsigned &BlockIndent, + unsigned BlockExitIndent, + unsigned &LineBreaks, bool &IsDone) { + unsigned MaxAllSpaceLineCharacters = 0; + StringRef::iterator LongestAllSpaceLine; + + while (true) { + advanceWhile(&Scanner::skip_s_space); + if (skip_nb_char(Current) != Current) { + // This line isn't empty, so try and find the indentation. + if (Column <= BlockExitIndent) { // End of the block literal. + IsDone = true; + return true; + } + // We found the block's indentation. + BlockIndent = Column; + if (MaxAllSpaceLineCharacters > BlockIndent) { + setError( + "Leading all-spaces line must be smaller than the block indent", + LongestAllSpaceLine); return false; } + return true; } - Current = i; + if (skip_b_break(Current) != Current && + Column > MaxAllSpaceLineCharacters) { + // Record the longest all-space line in case it's longer than the + // discovered block indent. + MaxAllSpaceLineCharacters = Column; + LongestAllSpaceLine = Current; + } + + // Check for EOF. + if (Current == End) { + IsDone = true; + return true; + } + + if (!consumeLineBreakIfPresent()) { + IsDone = true; + return true; + } + ++LineBreaks; + } + return true; +} + +bool Scanner::scanBlockScalarIndent(unsigned BlockIndent, + unsigned BlockExitIndent, bool &IsDone) { + // Skip the indentation. + while (Column < BlockIndent) { + auto I = skip_s_space(Current); + if (I == Current) + break; + Current = I; ++Column; } - if (Start == Current) { - setError("Got empty block scalar", Start); + if (skip_nb_char(Current) == Current) + return true; + + if (Column <= BlockExitIndent) { // End of the block literal. + IsDone = true; + return true; + } + + if (Column < BlockIndent) { + if (Current != End && *Current == '#') { // Trailing comment. + IsDone = true; + return true; + } + setError("A text line is less indented than the block scalar", Current); return false; } + return true; // A normal text line. +} + +bool Scanner::scanBlockScalar(bool IsLiteral) { + // Eat '|' or '>' + assert(*Current == '|' || *Current == '>'); + skip(1); + + char ChompingIndicator; + unsigned BlockIndent; + bool IsDone = false; + if (!scanBlockScalarHeader(ChompingIndicator, BlockIndent, IsDone)) + return false; + if (IsDone) + return true; + + auto Start = Current; + unsigned BlockExitIndent = Indent < 0 ? 0 : (unsigned)Indent; + unsigned LineBreaks = 0; + if (BlockIndent == 0) { + if (!findBlockScalarIndent(BlockIndent, BlockExitIndent, LineBreaks, + IsDone)) + return false; + } + + // Scan the block's scalars body. + SmallString<256> Str; + while (!IsDone) { + if (!scanBlockScalarIndent(BlockIndent, BlockExitIndent, IsDone)) + return false; + if (IsDone) + break; + + // Parse the current line. + auto LineStart = Current; + advanceWhile(&Scanner::skip_nb_char); + if (LineStart != Current) { + Str.append(LineBreaks, '\n'); + Str.append(StringRef(LineStart, Current - LineStart)); + LineBreaks = 0; + } + + // Check for EOF. + if (Current == End) + break; + + if (!consumeLineBreakIfPresent()) + break; + ++LineBreaks; + } + + if (Current == End && !LineBreaks) + // Ensure that there is at least one line break before the end of file. + LineBreaks = 1; + Str.append(getChompedLineBreaks(ChompingIndicator, LineBreaks, Str), '\n'); + + // New lines may start a simple key. + if (!FlowLevel) + IsSimpleKeyAllowed = true; Token T; - T.Kind = Token::TK_Scalar; + T.Kind = Token::TK_BlockScalar; T.Range = StringRef(Start, Current - Start); + T.Value = Str.str().str(); TokenQueue.push_back(T); return true; } @@ -1452,7 +1669,7 @@ bool Scanner::scanTag() { TokenQueue.push_back(T); // Tags can be simple keys. - saveSimpleKeyCandidate(TokenQueue.back(), ColStart, false); + saveSimpleKeyCandidate(--TokenQueue.end(), ColStart, false); IsSimpleKeyAllowed = false; @@ -1551,25 +1768,21 @@ bool Scanner::fetchMoreTokens() { return false; } -Stream::Stream(StringRef Input, SourceMgr &SM) - : scanner(new Scanner(Input, SM)) - , CurrentDoc(0) {} +Stream::Stream(StringRef Input, SourceMgr &SM, bool ShowColors) + : scanner(new Scanner(Input, SM, ShowColors)), CurrentDoc() {} -Stream::Stream(MemoryBuffer *InputBuffer, SourceMgr &SM) - : scanner(new Scanner(InputBuffer, SM)) - , CurrentDoc(0) {} +Stream::Stream(MemoryBufferRef InputBuffer, SourceMgr &SM, bool ShowColors) + : scanner(new Scanner(InputBuffer, SM, ShowColors)), CurrentDoc() {} Stream::~Stream() {} bool Stream::failed() { return scanner->failed(); } void Stream::printError(Node *N, const Twine &Msg) { - SmallVector Ranges; - Ranges.push_back(N->getSourceRange()); scanner->printError( N->getSourceRange().Start , SourceMgr::DK_Error , Msg - , Ranges); + , N->getSourceRange()); } document_iterator Stream::begin() { @@ -1592,11 +1805,9 @@ void Stream::skip() { i->skip(); } -Node::Node(unsigned int Type, OwningPtr &D, StringRef A, StringRef T) - : Doc(D) - , TypeID(Type) - , Anchor(A) - , Tag(T) { +Node::Node(unsigned int Type, std::unique_ptr &D, StringRef A, + StringRef T) + : Doc(D), TypeID(Type), Anchor(A), Tag(T) { SMLoc Start = SMLoc::getFromPointer(peekNext().Range.begin()); SourceRange = SMRange(Start, Start); } @@ -1608,11 +1819,11 @@ std::string Node::getVerbatimTag() const { if (Raw.find_last_of('!') == 0) { Ret = Doc->getTagMap().find("!")->second; Ret += Raw.substr(1); - return llvm_move(Ret); + return Ret; } else if (Raw.startswith("!!")) { Ret = Doc->getTagMap().find("!!")->second; Ret += Raw.substr(2); - return llvm_move(Ret); + return Ret; } else { StringRef TagHandle = Raw.substr(0, Raw.find_last_of('!') + 1); std::map::const_iterator It = @@ -1626,7 +1837,7 @@ std::string Node::getVerbatimTag() const { setError(Twine("Unknown tag handle ") + TagHandle, T); } Ret += Raw.substr(Raw.find_last_of('!') + 1); - return llvm_move(Ret); + return Ret; } } @@ -1634,6 +1845,7 @@ std::string Node::getVerbatimTag() const { case NK_Null: return "tag:yaml.org,2002:null"; case NK_Scalar: + case NK_BlockScalar: // TODO: Tag resolution. return "tag:yaml.org,2002:str"; case NK_Mapping: @@ -1910,14 +2122,14 @@ Node *KeyValueNode::getValue() { void MappingNode::increment() { if (failed()) { IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; return; } if (CurrentEntry) { CurrentEntry->skip(); if (Type == MT_Inline) { IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; return; } } @@ -1930,13 +2142,13 @@ void MappingNode::increment() { case Token::TK_BlockEnd: getNext(); IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; break; default: setError("Unexpected token. Expected Key or Block End", T); case Token::TK_Error: IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; } } else { switch (T.Kind) { @@ -1949,14 +2161,14 @@ void MappingNode::increment() { case Token::TK_Error: // Set this to end iterator. IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; break; default: setError( "Unexpected token. Expected Key, Flow Entry, or Flow " "Mapping End." , T); IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; } } } @@ -1964,7 +2176,7 @@ void MappingNode::increment() { void SequenceNode::increment() { if (failed()) { IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; return; } if (CurrentEntry) @@ -1975,37 +2187,37 @@ void SequenceNode::increment() { case Token::TK_BlockEntry: getNext(); CurrentEntry = parseBlockNode(); - if (CurrentEntry == 0) { // An error occurred. + if (!CurrentEntry) { // An error occurred. IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; } break; case Token::TK_BlockEnd: getNext(); IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; break; default: setError( "Unexpected token. Expected Block Entry or Block End." , T); case Token::TK_Error: IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; } } else if (SeqType == ST_Indentless) { switch (T.Kind) { case Token::TK_BlockEntry: getNext(); CurrentEntry = parseBlockNode(); - if (CurrentEntry == 0) { // An error occurred. + if (!CurrentEntry) { // An error occurred. IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; } break; default: case Token::TK_Error: IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; } } else if (SeqType == ST_Flow) { switch (T.Kind) { @@ -2019,7 +2231,7 @@ void SequenceNode::increment() { case Token::TK_Error: // Set this to end iterator. IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; break; case Token::TK_StreamEnd: case Token::TK_DocumentEnd: @@ -2027,13 +2239,13 @@ void SequenceNode::increment() { setError("Could not find closing ]!", T); // Set this to end iterator. IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; break; default: if (!WasPreviousTokenFlowEntry) { setError("Expected , between entries!", T); IsAtEnd = true; - CurrentEntry = 0; + CurrentEntry = nullptr; break; } // Otherwise it must be a flow entry. @@ -2047,7 +2259,7 @@ void SequenceNode::increment() { } } -Document::Document(Stream &S) : stream(S), Root(0) { +Document::Document(Stream &S) : stream(S), Root(nullptr) { // Tag maps starts with two default mappings. TagMap["!"] = "!"; TagMap["!!"] = "tag:yaml.org,2002:"; @@ -2104,7 +2316,7 @@ parse_property: case Token::TK_Anchor: if (AnchorInfo.Kind == Token::TK_Anchor) { setError("Already encountered an anchor for this node!", T); - return 0; + return nullptr; } AnchorInfo = getNext(); // Consume TK_Anchor. T = peekNext(); @@ -2112,7 +2324,7 @@ parse_property: case Token::TK_Tag: if (TagInfo.Kind == Token::TK_Tag) { setError("Already encountered a tag for this node!", T); - return 0; + return nullptr; } TagInfo = getNext(); // Consume TK_Tag. T = peekNext(); @@ -2165,6 +2377,14 @@ parse_property: , AnchorInfo.Range.substr(1) , TagInfo.Range , T.Range); + case Token::TK_BlockScalar: { + getNext(); + StringRef NullTerminatedStr(T.Value.c_str(), T.Value.length() + 1); + StringRef StrCopy = NullTerminatedStr.copy(NodeAllocator).drop_back(); + return new (NodeAllocator) + BlockScalarNode(stream.CurrentDoc, AnchorInfo.Range.substr(1), + TagInfo.Range, StrCopy, T.Range); + } case Token::TK_Key: // Don't eat the TK_Key, KeyValueNode expects it. return new (NodeAllocator) @@ -2180,10 +2400,10 @@ parse_property: // !!null null. return new (NodeAllocator) NullNode(stream.CurrentDoc); case Token::TK_Error: - return 0; + return nullptr; } llvm_unreachable("Control flow shouldn't reach here."); - return 0; + return nullptr; } bool Document::parseDirectives() {