| // Copyright 2018 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EXPR_TOKENIZER_H_ | |
| #define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EXPR_TOKENIZER_H_ | |
| #include <string> | |
| #include <string_view> | |
| #include <vector> | |
| #include "src/developer/debug/zxdb/common/err.h" | |
| #include "src/developer/debug/zxdb/expr/expr_language.h" | |
| #include "src/developer/debug/zxdb/expr/expr_token.h" | |
| #include "src/developer/debug/zxdb/symbols/dwarf_lang.h" | |
| namespace zxdb { | |
| class ExprTokenizer { | |
| public: | |
| explicit ExprTokenizer(const std::string& input, ExprLanguage lang = ExprLanguage::kC); | |
| // Returns true on successful tokenizing. In this case, the tokens can be read from tokens(). On | |
| // failure, err() will contain the error message, and error_location() will contain the error | |
| // location. | |
| bool Tokenize(); | |
| const std::string& input() const { return input_; } | |
| ExprLanguage language() const { return language_; } | |
| // The result of parsing. This will be multiline and will indicate the location of the problem. | |
| const Err& err() const { return err_; } | |
| // When err is set, this will be the index into the input() string where the | |
| // error occurred. | |
| size_t error_location() const { return error_location_; } | |
| // When parsing is successful, this contains the extracted tokens. | |
| const std::vector<ExprToken>& tokens() const { return tokens_; } | |
| std::vector<ExprToken> TakeTokens() { return std::move(tokens_); } | |
| // Returns whether the input is a valid unescaped name token. This does no trimming of whitespace | |
| // and does not accept "$" escaping. An empty string is not a valid name token. | |
| static bool IsNameToken(std::string_view input); | |
| // Returns two context lines for an error message. It will quote a relevant portion of the input | |
| // showing the byte offset, and add a "^" on the next line to indicate where the error is. | |
| static std::string GetErrorContext(const std::string& input, size_t byte_offset); | |
| private: | |
| void AdvanceChars(int n); | |
| void AdvanceOneChar(); | |
| void AdvanceToNextToken(); | |
| void AdvanceToEndOfToken(const ExprTokenRecord& record); | |
| bool IsCurrentWhitespace() const; | |
| // Returns true if the next characters in the buffer match the static value of the given token | |
| // record. If the token is alphanumeric, requires that the end of the token be nonalphanumeric. | |
| bool CurrentMatchesTokenRecord(const ExprTokenRecord& record) const; | |
| const ExprTokenRecord& ClassifyCurrent(); | |
| bool done() const { return at_end() || has_error(); } | |
| bool has_error() const { return err_.has_error(); } | |
| bool at_end() const { return cur_ == input_.size(); } | |
| char cur_char() const { return input_[cur_]; } | |
| bool can_advance(int n) const { return cur_ + n <= input_.size(); } | |
| std::string input_; | |
| ExprLanguage language_; | |
| size_t cur_ = 0; // Character offset into input_. | |
| Err err_; | |
| size_t error_location_ = 0; | |
| std::vector<ExprToken> tokens_; | |
| }; | |
| } // namespace zxdb | |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_EXPR_TOKENIZER_H_ |