diff options
Diffstat (limited to 'flang/lib/Parser/token-sequence.cpp')
-rw-r--r-- | flang/lib/Parser/token-sequence.cpp | 49 |
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 |