Add enum category example
This commit is contained in:
parent
0f9b90a32b
commit
0b71d7d3b4
5 changed files with 122 additions and 5 deletions
|
|
@ -10,5 +10,6 @@ endfunction()
|
|||
_cppast_example(ast_printer)
|
||||
_cppast_example(comparison)
|
||||
_cppast_example(documentation_generator)
|
||||
_cppast_example(enum_category)
|
||||
_cppast_example(enum_to_string)
|
||||
_cppast_example(serialization)
|
||||
|
|
|
|||
116
example/enum_category.cpp
Normal file
116
example/enum_category.cpp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
// Copyright (C) 2017 Jonathan Müller <jonathanmueller.dev@gmail.com>
|
||||
// This file is subject to the license terms in the LICENSE file
|
||||
// found in the top-level directory of this distribution.
|
||||
|
||||
/// \file
|
||||
/// Generates enum category functions.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include <cppast/cpp_enum.hpp> // cpp_enum
|
||||
#include <cppast/cpp_function.hpp> // cpp_function
|
||||
#include <cppast/visitor.hpp> // visit()
|
||||
|
||||
#include "example_parser.hpp"
|
||||
|
||||
bool is_category(const cppast::cpp_enum_value& e, const std::string& name)
|
||||
{
|
||||
if (auto attr = cppast::has_attribute(e, "generate::enum_category"))
|
||||
{
|
||||
auto iter =
|
||||
std::find_if(attr.value().arguments().value().begin(),
|
||||
attr.value().arguments().value().end(),
|
||||
[&](const cppast::cpp_token& tok) { return tok.spelling == name; });
|
||||
return iter != attr.value().arguments().value().end();
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
const cppast::cpp_enum& get_enum(const cppast::cpp_entity_index& index,
|
||||
const cppast::cpp_function_parameter& param)
|
||||
{
|
||||
auto& param_type = param.type();
|
||||
// is an enum
|
||||
assert(param_type.kind() == cppast::cpp_type_kind::user_defined_t);
|
||||
auto& definition =
|
||||
static_cast<const cppast::cpp_user_defined_type&>(param_type).entity().get(index)[0u].get();
|
||||
|
||||
assert(definition.kind() == cppast::cpp_entity_kind::enum_t);
|
||||
return static_cast<const cppast::cpp_enum&>(definition);
|
||||
}
|
||||
|
||||
void generate_enum_category(const cppast::cpp_entity_index& index, const cppast::cpp_file& file)
|
||||
{
|
||||
cppast::visit(file,
|
||||
[](const cppast::cpp_entity& e) {
|
||||
// only visit function declarations that have the attribute set
|
||||
return (e.kind() == cppast::cpp_entity_kind::function_t
|
||||
&& !cppast::is_definition(e)
|
||||
&& cppast::has_attribute(e, "generate::enum_category"))
|
||||
// or all namespaces
|
||||
|| e.kind() == cppast::cpp_entity_kind::namespace_t;
|
||||
},
|
||||
[&](const cppast::cpp_entity& e, const cppast::visitor_info& info) {
|
||||
if (e.kind() == cppast::cpp_entity_kind::function_t)
|
||||
{
|
||||
// a new function, generate implementation
|
||||
assert(info.is_new_entity());
|
||||
|
||||
auto category = cppast::has_attribute(e, "generate::enum_category")
|
||||
.value()
|
||||
.arguments()
|
||||
.value()
|
||||
.as_string();
|
||||
|
||||
auto& func = static_cast<const cppast::cpp_function&>(e);
|
||||
// return type must be bool
|
||||
assert(func.return_type().kind() == cppast::cpp_type_kind::builtin_t
|
||||
&& static_cast<const cppast::cpp_builtin_type&>(func.return_type())
|
||||
.builtin_type_kind()
|
||||
== cppast::cpp_bool);
|
||||
|
||||
// single parameter...
|
||||
assert(std::next(func.parameters().begin()) == func.parameters().end());
|
||||
auto& param = *func.parameters().begin();
|
||||
auto& enum_ = get_enum(index, param);
|
||||
|
||||
// generate function definition
|
||||
std::cout << "inline bool " << func.name() << "("
|
||||
<< cppast::to_string(param.type()) << " e) {\n";
|
||||
|
||||
// generate switch
|
||||
std::cout << " switch (e) {\n";
|
||||
for (const auto& enumerator : enum_)
|
||||
{
|
||||
std::cout << " case " << enum_.name() << "::" << enumerator.name()
|
||||
<< ":\n";
|
||||
if (is_category(enumerator, category))
|
||||
std::cout << " return true;\n";
|
||||
else
|
||||
std::cout << " return false;\n";
|
||||
}
|
||||
std::cout << " }\n";
|
||||
|
||||
std::cout << "}\n\n";
|
||||
}
|
||||
else if (e.kind() == cppast::cpp_entity_kind::namespace_t)
|
||||
{
|
||||
if (info.event == cppast::visitor_info::container_entity_enter)
|
||||
// open namespace
|
||||
std::cout << "namespace " << e.name() << " {\n\n";
|
||||
else // if (info.event == cppast::visitor_info::container_entity_exit)
|
||||
// close namespace
|
||||
std::cout << "}\n";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
cppast::cpp_entity_index index;
|
||||
return example_main(argc, argv, index,
|
||||
[&](const cppast::cpp_file& file) { generate_enum_category(index, file); });
|
||||
}
|
||||
|
|
@ -436,6 +436,9 @@ namespace cppast
|
|||
cpp_reference ref_;
|
||||
};
|
||||
|
||||
/// \returns The type as a string representation.
|
||||
std::string to_string(const cpp_type& type);
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
|
|
@ -453,9 +456,6 @@ namespace cppast
|
|||
// write prefix, variadic, name, suffix
|
||||
void write_type(code_generator::output& output, const cpp_type& type, std::string name,
|
||||
bool is_variadic = false);
|
||||
|
||||
// simple to_string() for types
|
||||
std::string to_string(const cpp_type& type);
|
||||
} // namespace detail
|
||||
} // namespace cppast
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ std::string cpp_function_base::do_get_signature() const
|
|||
{
|
||||
std::string result = "(";
|
||||
for (auto& param : parameters())
|
||||
result += detail::to_string(param.type()) + ',';
|
||||
result += to_string(param.type()) + ',';
|
||||
if (is_variadic())
|
||||
result += "...";
|
||||
|
||||
|
|
|
|||
|
|
@ -581,7 +581,7 @@ void detail::write_type(code_generator::output& output, const cpp_type& type, st
|
|||
write_type_suffix(output, type);
|
||||
}
|
||||
|
||||
std::string detail::to_string(const cpp_type& type)
|
||||
std::string cppast::to_string(const cpp_type& type)
|
||||
{
|
||||
class to_string_generator : public code_generator
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue