diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
commit | 676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch) | |
tree | 02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /lib/ASTMatchers/Dynamic/Parser.cpp | |
parent | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff) |
Diffstat (limited to 'lib/ASTMatchers/Dynamic/Parser.cpp')
-rw-r--r-- | lib/ASTMatchers/Dynamic/Parser.cpp | 106 |
1 files changed, 68 insertions, 38 deletions
diff --git a/lib/ASTMatchers/Dynamic/Parser.cpp b/lib/ASTMatchers/Dynamic/Parser.cpp index da8df907ba7f..5db10048fdf8 100644 --- a/lib/ASTMatchers/Dynamic/Parser.cpp +++ b/lib/ASTMatchers/Dynamic/Parser.cpp @@ -110,6 +110,10 @@ private: } switch (Code[0]) { + case '#': + Result.Kind = TokenInfo::TK_Eof; + Result.Text = ""; + return Result; case ',': Result.Kind = TokenInfo::TK_Comma; Result.Text = Code.substr(0, 1); @@ -339,8 +343,27 @@ bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) { if (const VariantValue NamedValue = NamedValues ? NamedValues->lookup(NameToken.Text) : VariantValue()) { - *Value = NamedValue; - return true; + + if (Tokenizer->nextTokenKind() != TokenInfo::TK_Period) { + *Value = NamedValue; + return true; + } + + std::string BindID; + if (!parseBindID(BindID)) + return false; + + assert(NamedValue.isMatcher()); + llvm::Optional<DynTypedMatcher> Result = + NamedValue.getMatcher().getSingleMatcher(); + if (Result.hasValue()) { + llvm::Optional<DynTypedMatcher> Bound = Result->tryBind(BindID); + if (Bound.hasValue()) { + *Value = VariantMatcher::SingleMatcher(*Bound); + return true; + } + } + return false; } // If the syntax is correct and the name is not a matcher either, report // unknown named value. @@ -359,6 +382,43 @@ bool Parser::parseIdentifierPrefixImpl(VariantValue *Value) { return parseMatcherExpressionImpl(NameToken, Value); } +bool Parser::parseBindID(std::string &BindID) { + // Parse .bind("foo") + assert(Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period); + Tokenizer->consumeNextToken(); // consume the period. + const TokenInfo BindToken = Tokenizer->consumeNextToken(); + if (BindToken.Kind == TokenInfo::TK_CodeCompletion) { + addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1)); + return false; + } + + const TokenInfo OpenToken = Tokenizer->consumeNextToken(); + const TokenInfo IDToken = Tokenizer->consumeNextToken(); + const TokenInfo CloseToken = Tokenizer->consumeNextToken(); + + // TODO: We could use different error codes for each/some to be more + // explicit about the syntax error. + if (BindToken.Kind != TokenInfo::TK_Ident || + BindToken.Text != TokenInfo::ID_Bind) { + Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr); + return false; + } + if (OpenToken.Kind != TokenInfo::TK_OpenParen) { + Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr); + return false; + } + if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) { + Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr); + return false; + } + if (CloseToken.Kind != TokenInfo::TK_CloseParen) { + Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr); + return false; + } + BindID = IDToken.Value.getString(); + return true; +} + /// Parse and validate a matcher expression. /// \return \c true on success, in which case \c Value has the matcher parsed. /// If the input is malformed, or some argument has an error, it @@ -425,38 +485,8 @@ bool Parser::parseMatcherExpressionImpl(const TokenInfo &NameToken, std::string BindID; if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) { - // Parse .bind("foo") - Tokenizer->consumeNextToken(); // consume the period. - const TokenInfo BindToken = Tokenizer->consumeNextToken(); - if (BindToken.Kind == TokenInfo::TK_CodeCompletion) { - addCompletion(BindToken, MatcherCompletion("bind(\"", "bind", 1)); + if (!parseBindID(BindID)) return false; - } - - const TokenInfo OpenToken = Tokenizer->consumeNextToken(); - const TokenInfo IDToken = Tokenizer->consumeNextToken(); - const TokenInfo CloseToken = Tokenizer->consumeNextToken(); - - // TODO: We could use different error codes for each/some to be more - // explicit about the syntax error. - if (BindToken.Kind != TokenInfo::TK_Ident || - BindToken.Text != TokenInfo::ID_Bind) { - Error->addError(BindToken.Range, Error->ET_ParserMalformedBindExpr); - return false; - } - if (OpenToken.Kind != TokenInfo::TK_OpenParen) { - Error->addError(OpenToken.Range, Error->ET_ParserMalformedBindExpr); - return false; - } - if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) { - Error->addError(IDToken.Range, Error->ET_ParserMalformedBindExpr); - return false; - } - if (CloseToken.Kind != TokenInfo::TK_CloseParen) { - Error->addError(CloseToken.Range, Error->ET_ParserMalformedBindExpr); - return false; - } - BindID = IDToken.Value.getString(); } if (!Ctor) @@ -619,12 +649,12 @@ Parser::completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S, P.parseExpressionImpl(&Dummy); // Sort by specificity, then by name. - llvm::sort(P.Completions.begin(), P.Completions.end(), + llvm::sort(P.Completions, [](const MatcherCompletion &A, const MatcherCompletion &B) { - if (A.Specificity != B.Specificity) - return A.Specificity > B.Specificity; - return A.TypedText < B.TypedText; - }); + if (A.Specificity != B.Specificity) + return A.Specificity > B.Specificity; + return A.TypedText < B.TypedText; + }); return P.Completions; } |