aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/RAIIObjectsForParser.h
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-06-06 21:18:07 +0000
committerDouglas Gregor <dgregor@apple.com>2012-06-06 21:18:07 +0000
commitc86c40b912e53fb11ff8f745ed616035b8b7259c (patch)
treeefeb4991d75fad4fc94f9305a45a16edee07a1b3 /lib/Parse/RAIIObjectsForParser.h
parent8d3607bf22a6a70acce3722a758f02d4ea84fc3a (diff)
Whenever we have a BalancedDelimiterTracker, we have a 'nested' scope
where '>' is going to behave as an operator (and not as a '>' closing a template argument list). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158111 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/RAIIObjectsForParser.h')
-rw-r--r--lib/Parse/RAIIObjectsForParser.h75
1 files changed, 75 insertions, 0 deletions
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
index 64431276bf..e13c4cfeb3 100644
--- a/lib/Parse/RAIIObjectsForParser.h
+++ b/lib/Parse/RAIIObjectsForParser.h
@@ -332,6 +332,81 @@ namespace clang {
}
};
+ /// \brief RAII class that helps handle the parsing of an open/close delimiter
+ /// pair, such as braces { ... } or parentheses ( ... ).
+ class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
+ Parser& P;
+ tok::TokenKind Kind, Close;
+ SourceLocation (Parser::*Consumer)();
+ SourceLocation LOpen, LClose;
+
+ unsigned short &getDepth() {
+ switch (Kind) {
+ case tok::l_brace: return P.BraceCount;
+ case tok::l_square: return P.BracketCount;
+ case tok::l_paren: return P.ParenCount;
+ default: llvm_unreachable("Wrong token kind");
+ }
+ }
+
+ enum { MaxDepth = 256 };
+
+ bool diagnoseOverflow();
+ bool diagnoseMissingClose();
+
+ public:
+ BalancedDelimiterTracker(Parser& p, tok::TokenKind k)
+ : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
+ P(p), Kind(k)
+ {
+ switch (Kind) {
+ default: llvm_unreachable("Unexpected balanced token");
+ case tok::l_brace:
+ Close = tok::r_brace;
+ Consumer = &Parser::ConsumeBrace;
+ break;
+ case tok::l_paren:
+ Close = tok::r_paren;
+ Consumer = &Parser::ConsumeParen;
+ break;
+
+ case tok::l_square:
+ Close = tok::r_square;
+ Consumer = &Parser::ConsumeBracket;
+ break;
+ }
+ }
+
+ SourceLocation getOpenLocation() const { return LOpen; }
+ SourceLocation getCloseLocation() const { return LClose; }
+ SourceRange getRange() const { return SourceRange(LOpen, LClose); }
+
+ bool consumeOpen() {
+ if (!P.Tok.is(Kind))
+ return true;
+
+ if (getDepth() < MaxDepth) {
+ LOpen = (P.*Consumer)();
+ return false;
+ }
+
+ return diagnoseOverflow();
+ }
+
+ bool expectAndConsume(unsigned DiagID,
+ const char *Msg = "",
+ tok::TokenKind SkipToTok = tok::unknown);
+ bool consumeClose() {
+ if (P.Tok.is(Close)) {
+ LClose = (P.*Consumer)();
+ return false;
+ }
+
+ return diagnoseMissingClose();
+ }
+ void skipToEnd();
+ };
+
} // end namespace clang
#endif