summaryrefslogtreecommitdiffstats
path: root/clang/lib/ASTMatchers/Dynamic/Parser.cpp
diff options
context:
space:
mode:
authorSamuel Benzaquen <sbenza@google.com>2013-06-03 19:31:08 +0000
committerSamuel Benzaquen <sbenza@google.com>2013-06-03 19:31:08 +0000
commit31edb51a4f274e97a9c54ae830b1896c690b8cf7 (patch)
treee53c1434bdb57c9c7b1cbf3bc6f542f333587ae6 /clang/lib/ASTMatchers/Dynamic/Parser.cpp
parentf102438f3a3215deb516059d8d003b18fdb125bd (diff)
downloadbcm5719-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.cpp72
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,
OpenPOWER on IntegriCloud