diff options
Diffstat (limited to 'lib/Format/FormatTokenLexer.cpp')
-rw-r--r-- | lib/Format/FormatTokenLexer.cpp | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp index 9778f84732d6..46a32a917dd9 100644 --- a/lib/Format/FormatTokenLexer.cpp +++ b/lib/Format/FormatTokenLexer.cpp @@ -26,12 +26,11 @@ namespace format { FormatTokenLexer::FormatTokenLexer(const SourceManager &SourceMgr, FileID ID, const FormatStyle &Style, encoding::Encoding Encoding) - : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false), - LessStashed(false), Column(0), TrailingWhitespace(0), - SourceMgr(SourceMgr), ID(ID), Style(Style), - IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable), - Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false), - MacroBlockBeginRegex(Style.MacroBlockBegin), + : FormatTok(nullptr), IsFirstToken(true), StateStack({LexerState::NORMAL}), + Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID), + Style(Style), IdentTable(getFormattingLangOpts(Style)), + Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0), + FormattingDisabled(false), MacroBlockBeginRegex(Style.MacroBlockBegin), MacroBlockEndRegex(Style.MacroBlockEnd) { Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr, getFormattingLangOpts(Style))); @@ -49,7 +48,7 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() { Tokens.push_back(getNextToken()); if (Style.Language == FormatStyle::LK_JavaScript) { tryParseJSRegexLiteral(); - tryParseTemplateString(); + handleTemplateStrings(); } tryMergePreviousTokens(); if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline) @@ -228,17 +227,44 @@ void FormatTokenLexer::tryParseJSRegexLiteral() { resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset))); } -void FormatTokenLexer::tryParseTemplateString() { +void FormatTokenLexer::handleTemplateStrings() { FormatToken *BacktickToken = Tokens.back(); - if (!BacktickToken->is(tok::unknown) || BacktickToken->TokenText != "`") + + if (BacktickToken->is(tok::l_brace)) { + StateStack.push(LexerState::NORMAL); return; + } + if (BacktickToken->is(tok::r_brace)) { + if (StateStack.size() == 1) + return; + StateStack.pop(); + if (StateStack.top() != LexerState::TEMPLATE_STRING) + return; + // If back in TEMPLATE_STRING, fallthrough and continue parsing the + } else if (BacktickToken->is(tok::unknown) && + BacktickToken->TokenText == "`") { + StateStack.push(LexerState::TEMPLATE_STRING); + } else { + return; // Not actually a template + } // 'Manually' lex ahead in the current file buffer. const char *Offset = Lex->getBufferLocation(); const char *TmplBegin = Offset - BacktickToken->TokenText.size(); // at "`" - for (; Offset != Lex->getBuffer().end() && *Offset != '`'; ++Offset) { - if (*Offset == '\\') + for (; Offset != Lex->getBuffer().end(); ++Offset) { + if (Offset[0] == '`') { + StateStack.pop(); + break; + } + if (Offset[0] == '\\') { ++Offset; // Skip the escaped character. + } else if (Offset + 1 < Lex->getBuffer().end() && Offset[0] == '$' && + Offset[1] == '{') { + // '${' introduces an expression interpolation in the template string. + StateStack.push(LexerState::NORMAL); + ++Offset; + break; + } } StringRef LiteralText(TmplBegin, Offset - TmplBegin + 1); @@ -262,7 +288,10 @@ void FormatTokenLexer::tryParseTemplateString() { Style.TabWidth, Encoding); } - resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset + 1))); + SourceLocation loc = Offset < Lex->getBuffer().end() + ? Lex->getSourceLocation(Offset + 1) + : SourceMgr.getLocForEndOfFile(ID); + resetLexer(SourceMgr.getFileOffset(loc)); } bool FormatTokenLexer::tryMerge_TMacro() { @@ -384,12 +413,8 @@ FormatToken *FormatTokenLexer::getStashedToken() { } FormatToken *FormatTokenLexer::getNextToken() { - if (GreaterStashed) { - GreaterStashed = false; - return getStashedToken(); - } - if (LessStashed) { - LessStashed = false; + if (StateStack.top() == LexerState::TOKEN_STASHED) { + StateStack.pop(); return getStashedToken(); } @@ -500,11 +525,13 @@ FormatToken *FormatTokenLexer::getNextToken() { } else if (FormatTok->Tok.is(tok::greatergreater)) { FormatTok->Tok.setKind(tok::greater); FormatTok->TokenText = FormatTok->TokenText.substr(0, 1); - GreaterStashed = true; + ++Column; + StateStack.push(LexerState::TOKEN_STASHED); } else if (FormatTok->Tok.is(tok::lessless)) { FormatTok->Tok.setKind(tok::less); FormatTok->TokenText = FormatTok->TokenText.substr(0, 1); - LessStashed = true; + ++Column; + StateStack.push(LexerState::TOKEN_STASHED); } // Now FormatTok is the next non-whitespace token. @@ -531,7 +558,8 @@ FormatToken *FormatTokenLexer::getNextToken() { Column = FormatTok->LastLineColumnWidth; } - if (Style.Language == FormatStyle::LK_Cpp) { + if (Style.Language == FormatStyle::LK_Cpp || + Style.Language == FormatStyle::LK_ObjC) { if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() && Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() == tok::pp_define) && |