diff options
author | Samuel Benzaquen <sbenza@google.com> | 2013-06-03 19:31:08 +0000 |
---|---|---|
committer | Samuel Benzaquen <sbenza@google.com> | 2013-06-03 19:31:08 +0000 |
commit | 31edb51a4f274e97a9c54ae830b1896c690b8cf7 (patch) | |
tree | e53c1434bdb57c9c7b1cbf3bc6f542f333587ae6 /clang/lib/ASTMatchers/Dynamic/Parser.cpp | |
parent | f102438f3a3215deb516059d8d003b18fdb125bd (diff) | |
download | bcm5719-llvm-31edb51a4f274e97a9c54ae830b1896c690b8cf7.tar.gz bcm5719-llvm-31edb51a4f274e97a9c54ae830b1896c690b8cf7.zip |
Add support for .bind("foo") expressions on the dynamic matchers.
Summary: Add support on the parser, registry, and DynTypedMatcher for binding IDs dynamically.
Reviewers: klimek
CC: cfe-commits, revane
Differential Revision: http://llvm-reviews.chandlerc.com/D911
llvm-svn: 183144
Diffstat (limited to 'clang/lib/ASTMatchers/Dynamic/Parser.cpp')
-rw-r--r-- | clang/lib/ASTMatchers/Dynamic/Parser.cpp | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/clang/lib/ASTMatchers/Dynamic/Parser.cpp b/clang/lib/ASTMatchers/Dynamic/Parser.cpp index 1678820da01..1ed40f3050f 100644 --- a/clang/lib/ASTMatchers/Dynamic/Parser.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Parser.cpp @@ -32,12 +32,16 @@ struct Parser::TokenInfo { TK_OpenParen = 1, TK_CloseParen = 2, TK_Comma = 3, - TK_Literal = 4, - TK_Ident = 5, - TK_InvalidChar = 6, - TK_Error = 7 + TK_Period = 4, + TK_Literal = 5, + TK_Ident = 6, + TK_InvalidChar = 7, + TK_Error = 8 }; + /// \brief Some known identifiers. + static const char* const ID_Bind; + TokenInfo() : Text(), Kind(TK_Eof), Range(), Value() {} StringRef Text; @@ -46,6 +50,8 @@ struct Parser::TokenInfo { VariantValue Value; }; +const char* const Parser::TokenInfo::ID_Bind = "bind"; + /// \brief Simple tokenizer for the parser. class Parser::CodeTokenizer { public: @@ -84,6 +90,11 @@ private: Result.Text = Code.substr(0, 1); Code = Code.drop_front(); break; + case '.': + Result.Kind = TokenInfo::TK_Period; + Result.Text = Code.substr(0, 1); + Code = Code.drop_front(); + break; case '(': Result.Kind = TokenInfo::TK_OpenParen; Result.Text = Code.substr(0, 1); @@ -234,11 +245,43 @@ bool Parser::parseMatcherExpressionImpl(VariantValue *Value) { return false; } + std::string BindID; + if (Tokenizer->peekNextToken().Kind == TokenInfo::TK_Period) { + // Parse .bind("foo") + Tokenizer->consumeNextToken(); // consume the period. + const TokenInfo BindToken = Tokenizer->consumeNextToken(); + 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->pushErrorFrame(BindToken.Range, Error->ET_ParserMalformedBindExpr); + return false; + } + if (OpenToken.Kind != TokenInfo::TK_OpenParen) { + Error->pushErrorFrame(OpenToken.Range, Error->ET_ParserMalformedBindExpr); + return false; + } + if (IDToken.Kind != TokenInfo::TK_Literal || !IDToken.Value.isString()) { + Error->pushErrorFrame(IDToken.Range, Error->ET_ParserMalformedBindExpr); + return false; + } + if (CloseToken.Kind != TokenInfo::TK_CloseParen) { + Error->pushErrorFrame(CloseToken.Range, + Error->ET_ParserMalformedBindExpr); + return false; + } + BindID = IDToken.Value.getString(); + } + // Merge the start and end infos. SourceRange MatcherRange = NameToken.Range; MatcherRange.End = EndToken.Range.End; - DynTypedMatcher *Result = - S->actOnMatcherExpression(NameToken.Text, MatcherRange, Args, Error); + DynTypedMatcher *Result = S->actOnMatcherExpression( + NameToken.Text, MatcherRange, BindID, Args, Error); if (Result == NULL) { Error->pushErrorFrame(NameToken.Range, Error->ET_ParserMatcherFailure) << NameToken.Text; @@ -271,6 +314,7 @@ bool Parser::parseExpressionImpl(VariantValue *Value) { case TokenInfo::TK_OpenParen: case TokenInfo::TK_CloseParen: case TokenInfo::TK_Comma: + case TokenInfo::TK_Period: case TokenInfo::TK_InvalidChar: const TokenInfo Token = Tokenizer->consumeNextToken(); Error->pushErrorFrame(Token.Range, Error->ET_ParserInvalidToken) @@ -290,9 +334,15 @@ public: virtual ~RegistrySema() {} DynTypedMatcher *actOnMatcherExpression(StringRef MatcherName, const SourceRange &NameRange, + StringRef BindID, ArrayRef<ParserValue> Args, Diagnostics *Error) { - return Registry::constructMatcher(MatcherName, NameRange, Args, Error); + if (BindID.empty()) { + return Registry::constructMatcher(MatcherName, NameRange, Args, Error); + } else { + return Registry::constructBoundMatcher(MatcherName, NameRange, BindID, + Args, Error); + } } }; @@ -305,7 +355,13 @@ bool Parser::parseExpression(StringRef Code, VariantValue *Value, bool Parser::parseExpression(StringRef Code, Sema *S, VariantValue *Value, Diagnostics *Error) { CodeTokenizer Tokenizer(Code, Error); - return Parser(&Tokenizer, S, Error).parseExpressionImpl(Value); + if (!Parser(&Tokenizer, S, Error).parseExpressionImpl(Value)) return false; + if (Tokenizer.peekNextToken().Kind != TokenInfo::TK_Eof) { + Error->pushErrorFrame(Tokenizer.peekNextToken().Range, + Error->ET_ParserTrailingCode); + return false; + } + return true; } DynTypedMatcher *Parser::parseMatcherExpression(StringRef Code, |