|  | // 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_ |