| // Copyright 2019 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. |
| |
| // This header defines internal structures used by the parser to help it manage state during |
| // a parse. |
| |
| #ifndef SRC_CONNECTIVITY_NETWORK_NETDUMP_PARSER_STATE_H_ |
| #define SRC_CONNECTIVITY_NETWORK_NETDUMP_PARSER_STATE_H_ |
| |
| #include <zircon/assert.h> |
| |
| #include <iterator> |
| #include <optional> |
| #include <string> |
| #include <vector> |
| |
| #include "tokens.h" |
| |
| namespace netdump::parser { |
| |
| using TokenIterator = std::vector<TokenPtr>::iterator; |
| |
| // Parse state values for when a binary logical operator is encountered. |
| enum class ParseOp { |
| NONE, |
| CONJ, // Logical `AND`. |
| DISJ, // Logical `OR`. |
| }; |
| |
| class ParseOpState { |
| public: |
| // Track if the parse has encountered a binary operation. |
| ParseOp op = ParseOp::NONE; |
| // Track how many negations the current parse is under. |
| // The number of negations is tracked so e.g. `not not` can be differentiated from no negation. |
| size_t negations = 0; |
| }; |
| |
| // An `Environment` object represents the parse environment. It can be seen as a state machine that |
| // keeps track of the parse cursor, i.e. the token location that the parser has reached. |
| // The states are positions along the series of tokens that need to be parser. If an error has been |
| // encountered within the parse, data relevant for reporting the error can be recorded here. |
| // Exactly one instance of `Environment` should be created at the beginning of a parse attempt for |
| // use until the end of the attempt. `Environment` is therefore movable but not copyable to help |
| // enforce this. |
| class Environment { |
| public: |
| // An instance is constructed from a vector of tokens that needs to be parsed. |
| explicit Environment(std::vector<TokenPtr> tokens) |
| : tokens_(std::move(tokens)), begin_(tokens_.begin()), cur_(begin_), end_(tokens_.end()) {} |
| |
| // Movable but not copyable. |
| Environment(Environment&& other) = default; |
| Environment& operator=(Environment&& other) = default; |
| Environment(const Environment&) = delete; |
| Environment& operator=(const Environment&) = delete; |
| |
| // Return the first token location to be parsed. |
| [[nodiscard]] inline TokenIterator begin() const { return begin_; } |
| |
| // Return the current token location under parse. |
| [[nodiscard]] inline TokenIterator cur() const { return cur_; } |
| |
| // Return the location beyond the last token to be parsed. |
| [[nodiscard]] inline TokenIterator end() const { return end_; } |
| |
| [[nodiscard]] inline bool at_end() const { return cur_ == end_; } |
| |
| // Reset the token location under parse to the beginning. |
| // Does not clear the error data. |
| inline void reset() { cur_ = begin_; } |
| |
| // Clear the error data. |
| inline void clear_error() { |
| error_cause.clear(); |
| error_loc = std::nullopt; |
| } |
| |
| inline bool has_error() { return (error_loc != std::nullopt); } |
| |
| // Operators to get the token at the current location, and to change the location. |
| TokenPtr operator*() { |
| ZX_DEBUG_ASSERT_MSG(cur_ < end_, "Dereferencing end token location."); |
| return *cur_; |
| } |
| Environment& operator++() { |
| if (cur_ < end_) { |
| ++cur_; |
| } |
| return (*this); |
| } |
| Environment& operator--() { |
| if (cur_ > begin_) { |
| --cur_; |
| } |
| return (*this); |
| } |
| |
| // Data for any error that was encountered. |
| std::string error_cause{}; |
| std::optional<TokenIterator> error_loc{}; |
| |
| private: |
| std::vector<TokenPtr> tokens_; |
| TokenIterator begin_; |
| TokenIterator cur_; |
| TokenIterator end_; |
| }; |
| |
| } // namespace netdump::parser |
| |
| #endif // SRC_CONNECTIVITY_NETWORK_NETDUMP_PARSER_STATE_H_ |