aboutsummaryrefslogtreecommitdiff
path: root/flang/lib/Parser/token-sequence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'flang/lib/Parser/token-sequence.cpp')
-rw-r--r--flang/lib/Parser/token-sequence.cpp49
1 files changed, 39 insertions, 10 deletions
diff --git a/flang/lib/Parser/token-sequence.cpp b/flang/lib/Parser/token-sequence.cpp
index 3ed9d05..55217a9 100644
--- a/flang/lib/Parser/token-sequence.cpp
+++ b/flang/lib/Parser/token-sequence.cpp
@@ -27,6 +27,8 @@ void TokenSequence::clear() {
}
void TokenSequence::pop_back() {
+ CHECK(!start_.empty());
+ CHECK(nextStart_ > start_.back());
std::size_t bytes{nextStart_ - start_.back()};
nextStart_ = start_.back();
start_.pop_back();
@@ -82,16 +84,6 @@ bool TokenSequence::IsAnythingLeft(std::size_t at) const {
return false;
}
-void TokenSequence::RemoveLastToken() {
- CHECK(!start_.empty());
- CHECK(nextStart_ > start_.back());
- std::size_t bytes{nextStart_ - start_.back()};
- nextStart_ = start_.back();
- start_.pop_back();
- char_.erase(char_.begin() + nextStart_, char_.end());
- provenances_.RemoveLastBytes(bytes);
-}
-
void TokenSequence::Put(const TokenSequence &that) {
if (nextStart_ < char_.size()) {
start_.push_back(nextStart_);
@@ -338,4 +330,41 @@ const TokenSequence &TokenSequence::CheckBadFortranCharacters(
}
return *this;
}
+
+const TokenSequence &TokenSequence::CheckBadParentheses(
+ Messages &messages) const {
+ // First, a quick pass with no allocation for the common case
+ int nesting{0};
+ std::size_t tokens{SizeInTokens()};
+ for (std::size_t j{0}; j < tokens; ++j) {
+ CharBlock token{TokenAt(j)};
+ char ch{token.FirstNonBlank()};
+ if (ch == '(') {
+ ++nesting;
+ } else if (ch == ')') {
+ --nesting;
+ }
+ }
+ if (nesting != 0) {
+ // There's an error; diagnose it
+ std::vector<std::size_t> stack;
+ for (std::size_t j{0}; j < tokens; ++j) {
+ CharBlock token{TokenAt(j)};
+ char ch{token.FirstNonBlank()};
+ if (ch == '(') {
+ stack.push_back(j);
+ } else if (ch == ')') {
+ if (stack.empty()) {
+ messages.Say(GetTokenProvenanceRange(j), "Unmatched ')'"_err_en_US);
+ return *this;
+ }
+ stack.pop_back();
+ }
+ }
+ CHECK(!stack.empty());
+ messages.Say(
+ GetTokenProvenanceRange(stack.back()), "Unmatched '('"_err_en_US);
+ }
+ return *this;
+}
} // namespace Fortran::parser