Parse enums
This commit is contained in:
parent
0794ff1420
commit
a47e66e2c4
16 changed files with 262 additions and 109 deletions
82
src/libclang/enum_parser.cpp
Normal file
82
src/libclang/enum_parser.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// 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.
|
||||
|
||||
#include <cppast/cpp_enum.hpp>
|
||||
|
||||
#include "parse_functions.hpp"
|
||||
#include "libclang_visitor.hpp"
|
||||
|
||||
using namespace cppast;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unique_ptr<cpp_enum_value> parse_enum_value(const detail::parse_context& context,
|
||||
const CXCursor& cur)
|
||||
{
|
||||
DEBUG_ASSERT(cur.kind == CXCursor_EnumConstantDecl, detail::parse_error_handler{}, cur,
|
||||
"unexpected child cursor of enum");
|
||||
|
||||
detail::tokenizer tokenizer(context.tu, context.file, cur);
|
||||
detail::token_stream stream(tokenizer, cur);
|
||||
|
||||
// <identifier>,
|
||||
// or: <identifier> = <expression>,
|
||||
auto& name = stream.get().value();
|
||||
|
||||
std::unique_ptr<cpp_expression> value;
|
||||
if (detail::skip_if(stream, "="))
|
||||
{
|
||||
detail::visit_children(cur, [&](const CXCursor& child) {
|
||||
DEBUG_ASSERT(clang_isExpression(child.kind) && !value,
|
||||
detail::parse_error_handler{}, cur,
|
||||
"unexpected child cursor of enum value");
|
||||
|
||||
value = detail::parse_expression(context, child);
|
||||
});
|
||||
}
|
||||
|
||||
return cpp_enum_value::build(*context.idx, detail::get_entity_id(cur), name.c_str(),
|
||||
std::move(value));
|
||||
}
|
||||
|
||||
cpp_enum::builder make_enum_builder(const detail::parse_context& context, const CXCursor& cur)
|
||||
{
|
||||
detail::tokenizer tokenizer(context.tu, context.file, cur);
|
||||
detail::token_stream stream(tokenizer, cur);
|
||||
|
||||
// enum [class] name [: type] {
|
||||
detail::skip(stream, "enum");
|
||||
auto scoped = detail::skip_if(stream, "class");
|
||||
auto& name = stream.get().value();
|
||||
|
||||
std::unique_ptr<cpp_type> type;
|
||||
if (detail::skip_if(stream, ":"))
|
||||
// parse type, explictly given one
|
||||
type = detail::parse_type(context, clang_getEnumDeclIntegerType(cur));
|
||||
|
||||
return cpp_enum::builder(name.c_str(), scoped, std::move(type));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_entity> detail::parse_cpp_enum(const detail::parse_context& context,
|
||||
const CXCursor& cur)
|
||||
{
|
||||
DEBUG_ASSERT(cur.kind == CXCursor_EnumDecl, detail::assert_handler{});
|
||||
if (!clang_isCursorDefinition(cur))
|
||||
return nullptr;
|
||||
|
||||
auto builder = make_enum_builder(context, cur);
|
||||
detail::visit_children(cur, [&](const CXCursor& child) {
|
||||
try
|
||||
{
|
||||
auto entity = parse_enum_value(context, child);
|
||||
builder.add_value(std::move(entity));
|
||||
}
|
||||
catch (parse_error& ex)
|
||||
{
|
||||
context.logger->log("libclang parser", ex.get_diagnostic());
|
||||
}
|
||||
});
|
||||
return builder.finish(*context.idx, get_entity_id(cur));
|
||||
}
|
||||
34
src/libclang/expression_parser.cpp
Normal file
34
src/libclang/expression_parser.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// 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.
|
||||
|
||||
#include <cppast/cpp_expression.hpp>
|
||||
|
||||
#include "parse_functions.hpp"
|
||||
|
||||
using namespace cppast;
|
||||
|
||||
std::unique_ptr<cpp_expression> detail::parse_expression(const detail::parse_context& context,
|
||||
const CXCursor& cur)
|
||||
{
|
||||
auto kind = clang_getCursorKind(cur);
|
||||
DEBUG_ASSERT(clang_isExpression(kind), detail::assert_handler{});
|
||||
|
||||
detail::tokenizer tokenizer(context.tu, context.file, cur);
|
||||
detail::token_stream stream(tokenizer, cur);
|
||||
|
||||
// just concat everything
|
||||
std::string expr;
|
||||
while (!stream.done())
|
||||
expr += stream.get().c_str();
|
||||
|
||||
auto type = parse_type(context, clang_getCursorType(cur));
|
||||
|
||||
if (kind == CXCursor_CharacterLiteral || kind == CXCursor_CompoundLiteralExpr
|
||||
|| kind == CXCursor_FloatingLiteral || kind == CXCursor_ImaginaryLiteral
|
||||
|| kind == CXCursor_IntegerLiteral || kind == CXCursor_StringLiteral
|
||||
|| kind == CXCursor_CXXBoolLiteralExpr || kind == CXCursor_CXXNullPtrLiteralExpr)
|
||||
return cpp_literal_expression::build(std::move(type), std::move(expr));
|
||||
else
|
||||
return cpp_unexposed_expression::build(std::move(type), std::move(expr));
|
||||
}
|
||||
|
|
@ -38,6 +38,9 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
|
|||
case CXCursor_TypedefDecl:
|
||||
return parse_cpp_type_alias(context, cur);
|
||||
|
||||
case CXCursor_EnumDecl:
|
||||
return parse_cpp_enum(context, cur);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
namespace cppast
|
||||
{
|
||||
class cpp_expression;
|
||||
class cpp_type;
|
||||
|
||||
namespace detail
|
||||
|
|
@ -30,6 +31,9 @@ namespace cppast
|
|||
|
||||
std::unique_ptr<cpp_type> parse_type(const parse_context& context, const CXType& type);
|
||||
|
||||
std::unique_ptr<cpp_expression> parse_expression(const parse_context& context,
|
||||
const CXCursor& cur);
|
||||
|
||||
// parse_entity() dispatches on the cursor type
|
||||
// it calls one of the other parse functions defined elsewhere
|
||||
// try_parse_XXX are not exposed entities
|
||||
|
|
@ -50,6 +54,9 @@ namespace cppast
|
|||
std::unique_ptr<cpp_entity> parse_cpp_type_alias(const parse_context& context,
|
||||
const CXCursor& cur);
|
||||
|
||||
std::unique_ptr<cpp_entity> parse_cpp_enum(const parse_context& context,
|
||||
const CXCursor& cur);
|
||||
|
||||
std::unique_ptr<cpp_entity> parse_entity(const parse_context& context, const CXCursor& cur);
|
||||
}
|
||||
} // namespace cppast::detail
|
||||
|
|
|
|||
|
|
@ -152,6 +152,9 @@ namespace
|
|||
} while (!token_after_is(tu, file, cur, end, ";"));
|
||||
end = get_next_location(tu, file, end);
|
||||
}
|
||||
else if (clang_isExpression(clang_getCursorKind(cur)))
|
||||
// need to shrink range by one
|
||||
end = get_next_location(tu, file, end, -1);
|
||||
|
||||
return clang_getRange(begin, end);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -399,17 +399,12 @@ namespace
|
|||
}
|
||||
|
||||
std::unique_ptr<cpp_type> detail::parse_type(const detail::parse_context& context,
|
||||
const CXType& type) try
|
||||
const CXType& type)
|
||||
{
|
||||
auto result = parse_type_impl(context, type);
|
||||
DEBUG_ASSERT(result && is_valid(*result), detail::parse_error_handler{}, type, "invalid type");
|
||||
return std::move(result);
|
||||
}
|
||||
catch (parse_error& ex)
|
||||
{
|
||||
context.logger->log("libclang parser", ex.get_diagnostic());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<cpp_entity> detail::parse_cpp_type_alias(const detail::parse_context& context,
|
||||
const CXCursor& cur)
|
||||
|
|
@ -419,7 +414,5 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_type_alias(const detail::parse_con
|
|||
|
||||
auto name = cxstring(clang_getCursorSpelling(cur));
|
||||
auto type = parse_type(context, clang_getTypedefDeclUnderlyingType(cur));
|
||||
if (!type)
|
||||
return nullptr;
|
||||
return cpp_type_alias::build(*context.idx, get_entity_id(cur), name.c_str(), std::move(type));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue