| // Copyright 2017-2020 The Verible Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // MacroDefinition is the structural representation of a macro definition. |
| // The structure is language-agnostic, but was developed with Verilog in mind. |
| |
| #ifndef VERIBLE_COMMON_TEXT_MACRO_DEFINITION_H_ |
| #define VERIBLE_COMMON_TEXT_MACRO_DEFINITION_H_ |
| |
| #include <cstddef> |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/status/status.h" |
| #include "absl/strings/string_view.h" |
| #include "common/text/token_info.h" |
| |
| namespace verible { |
| |
| // For use in containers, we need a TokenInfo that is default constructible. |
| // Apart from that, it is no different than TokenInfo. |
| struct DefaultTokenInfo : public TokenInfo { |
| DefaultTokenInfo() : TokenInfo(TokenInfo::EOFToken()) {} |
| |
| // Accept a plain TokenInfo for copy purposes. |
| explicit DefaultTokenInfo(const TokenInfo& t) : TokenInfo(t) {} |
| |
| // Accept a plain TokenInfo for assignment purposes. |
| DefaultTokenInfo& operator=(const TokenInfo& t) { |
| TokenInfo::operator=(t); |
| return *this; |
| } |
| }; |
| |
| // Macro formal parameter specification: name with optional default. |
| struct MacroParameterInfo { |
| explicit MacroParameterInfo(const TokenInfo& n = TokenInfo::EOFToken(), |
| const TokenInfo& d = TokenInfo::EOFToken()) |
| : name(n), default_value(d) {} |
| |
| // Name of macro parameter. |
| TokenInfo name; |
| |
| // Macro parameters may have default values. [Verilog] |
| TokenInfo default_value; |
| |
| bool HasDefaultText() const { return !default_value.text().empty(); } |
| }; |
| |
| // MacroCall is a reference to a macro, such as `MACRO or `MACRO(...). |
| struct MacroCall { |
| // Name of macro. |
| DefaultTokenInfo macro_name; |
| |
| // Distinguish between a definition without () vs. with empty (). |
| bool has_parameters; |
| |
| // Positional arguments to macro call. |
| std::vector<DefaultTokenInfo> positional_arguments; |
| |
| MacroCall() : has_parameters(false) {} |
| }; |
| |
| class MacroDefinition { |
| public: |
| MacroDefinition(const TokenInfo& header, const TokenInfo& name) |
| : header_(header), name_(name), is_callable_(false) {} |
| |
| absl::string_view Name() const { return name_.text(); } |
| const TokenInfo& NameToken() const { return name_; } |
| |
| const TokenInfo& DefinitionText() const { return definition_text_; } |
| |
| void SetDefinitionText(const TokenInfo& t) { definition_text_ = t; } |
| |
| // Macro definitions with empty () should call this. |
| void SetCallable() { is_callable_ = true; } |
| |
| bool IsCallable() const { return is_callable_; } |
| |
| // Add a formal parameter to macro definition. |
| // Returns true if parameter was successfully added. |
| // Duplicate parameter names are rejected, and will return false. |
| // This automatically sets is_callable_. |
| bool AppendParameter(const MacroParameterInfo&); |
| |
| const std::vector<MacroParameterInfo>& Parameters() const { |
| return parameter_info_array_; |
| } |
| |
| typedef std::map<absl::string_view, DefaultTokenInfo> substitution_map_type; |
| |
| // Create a text substitution map to be used for macro expansion. |
| absl::Status PopulateSubstitutionMap(const std::vector<TokenInfo>&, |
| substitution_map_type*) const; |
| absl::Status PopulateSubstitutionMap(const std::vector<DefaultTokenInfo>&, |
| substitution_map_type*) const; |
| |
| // Replace formal parameter references with actuals. |
| static const TokenInfo& SubstituteText(const substitution_map_type&, |
| const TokenInfo&, |
| int actual_token_enum = 0); |
| |
| private: |
| TokenInfo header_; // e.g. "#define" or "`define" |
| |
| // Name of macro definition. Is const because name_ determines |
| // ordering within an ordered set, and thus, should be immutable. |
| TokenInfo name_; |
| |
| // Distinguish between a definition without () vs. with empty (). |
| bool is_callable_; |
| |
| // These form an ordered dictionary on macro parameters. |
| std::vector<MacroParameterInfo> parameter_info_array_; |
| std::map<std::string, size_t> parameter_positions_; |
| |
| // un-tokenized text |
| DefaultTokenInfo definition_text_; |
| }; |
| |
| } // namespace verible |
| |
| #endif // VERIBLE_COMMON_TEXT_MACRO_DEFINITION_H_ |