| // 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. |
| |
| #pragma once |
| |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "garnet/bin/zxdb/common/err.h" |
| #include "garnet/bin/zxdb/expr/expr_token.h" |
| |
| namespace zxdb { |
| |
| class Err; |
| |
| // An identifier is a sequence of names. Currently this handles C++ and Rust, |
| // but could be enhanced in the future for other languages. |
| // |
| // This is used for variable names and function names. If you type a class |
| // name or a typedef, the parser will also parse it as an identifier. What |
| // the identifier actually means will depend on the context in which it's used. |
| // |
| // One component can consist of a name and a template part (note currently the |
| // parser doesn't support the template part, but this class does in expectation |
| // that parsing support will be added in the future). |
| // |
| // Component := [ "::" ] <Name> [ "<" <Template-Goop> ">" ] |
| // |
| // An identifier consists of one or more components. In C++, if the first |
| // component has a valid separator token, it's fully qualified ("::foo"), but |
| // it could be omitted for non-fully-qualified names. Subsequent components |
| // will always have separators. |
| // |
| // The identifier contains the token information for the original so that |
| // it can be used for syntax highlighting. |
| class Identifier { |
| public: |
| class Component { |
| public: |
| Component(); |
| |
| // Constructor for names without templates. |
| Component(ExprToken separator, ExprToken name) |
| : separator_(std::move(separator)), name_(std::move(name)) {} |
| |
| // Constructor for names without templates for use by tests that hard-code |
| // values. |
| Component(bool has_separator, const std::string& name) |
| : name_(ExprToken::kName, name, 0) { |
| if (has_separator) |
| separator_ = ExprToken(ExprToken::kColonColon, "::", 0); |
| } |
| |
| // Constructor for names with templates. The contents will be a |
| // vector of somewhat-normalized type string in between the <>. |
| Component(ExprToken separator, ExprToken name, ExprToken template_begin, |
| std::vector<std::string> template_contents, |
| ExprToken template_end) |
| : separator_(std::move(separator)), |
| name_(std::move(name)), |
| template_begin_(std::move(template_begin)), |
| template_contents_(std::move(template_contents)), |
| template_end_(std::move(template_end)) {} |
| |
| bool has_separator() const { |
| return separator_.type() != ExprToken::kInvalid; |
| } |
| bool has_template() const { |
| return template_begin_.type() != ExprToken::kInvalid; |
| } |
| |
| const ExprToken& separator() const { return separator_; } |
| void set_separator(ExprToken t) { separator_ = std::move(t); } |
| |
| const ExprToken& name() const { return name_; } |
| |
| // This will be kInvalid if there is no template on this component. |
| // The begin and end are the <> tokens, and the contents is the normalized |
| // string in between. Note that the contents may not exactly match the |
| // input string (some whitespace may be removed). |
| const ExprToken& template_begin() const { return template_begin_; } |
| const std::vector<std::string>& template_contents() const { |
| return template_contents_; |
| } |
| const ExprToken& template_end() const { return template_end_; } |
| |
| private: |
| ExprToken separator_; |
| ExprToken name_; |
| |
| ExprToken template_begin_; |
| std::vector<std::string> template_contents_; |
| ExprToken template_end_; |
| }; |
| |
| Identifier() = default; |
| |
| // Makes a simple identifier with a standalone name. |
| explicit Identifier(ExprToken name); |
| |
| // Makes an identifier from a single component. |
| explicit Identifier(Component comp); |
| |
| // Attempts to parse the given string as an identifier. Returns either a |
| // set Err or the resulting Identifier when the Err is not set. |
| static std::pair<Err, Identifier> FromString(const std::string& input); |
| |
| // Makes an identifier over a range of components. |
| template <class InputIterator> |
| Identifier(InputIterator first, InputIterator last) |
| : components_(first, last) {} |
| |
| std::vector<Component>& components() { return components_; } |
| const std::vector<Component>& components() const { return components_; } |
| |
| void AppendComponent(Component c); |
| void AppendComponent(ExprToken separator, ExprToken name); |
| void AppendComponent(ExprToken separator, ExprToken name, |
| ExprToken template_begin, |
| std::vector<std::string> template_contents, |
| ExprToken template_end); |
| |
| // Returns a new identifier that's the scope of this one. The scope is |
| // everything but the last identifier. |
| // |
| // If there is only one component, the resulting identifier will either be |
| // empty (if the component has no separator, e.g. "Foo" becomes ""), or |
| // contain only a separator (if the component has a separator, e.g. "::Foo" |
| // becomes "::" and "::" becomes itself). |
| Identifier GetScope() const; |
| |
| // Returns true if this identifier begins with "::" and as such can only be |
| // resolved in the global namespace. |
| bool InGlobalNamespace() const; |
| |
| // Returns the full name with all components concatenated together. |
| std::string GetFullName() const; |
| |
| // Returns a form for debugging where the parsing is more visible. |
| std::string GetDebugName() const; |
| |
| // In many contexts (like function parameters and local variables) the name |
| // can't have any :: or template parameters and can have only one component. |
| // If this identifier satisfies this requirement, a pointer to the single |
| // string is returned. If there is zero or more than one component or any |
| // template specs, returns null. |
| // |
| // The returned pointer will be invalidated if the Identifier is mutated. |
| const std::string* GetSingleComponentName() const; |
| |
| private: |
| // Backend for the name getters. |
| std::string GetName(bool include_debug) const; |
| |
| std::vector<Component> components_; |
| }; |
| |
| } // namespace zxdb |