6#ifndef MIMICPP_PRINTING_TYPE_PARSER_HPP
7#define MIMICPP_PRINTING_TYPE_PARSER_HPP
18#ifndef MIMICPP_DETAIL_IS_MODULE
36 while (!std::holds_alternative<lexing::end>(lexer.peek().classification))
38 if (
auto token = lexer.next();
39 !std::holds_alternative<lexing::space>(token.classification))
41 m_Tokens.emplace_back(std::move(token));
45 m_Tokens.emplace_back(lexer.next());
49 constexpr bool is_eof() const noexcept
51 return m_Index == std::ranges::size(m_Tokens) - 1u;
57 MIMICPP_ASSERT(m_Index < std::ranges::size(m_Tokens),
"Stream is at end.");
58 return std::span{m_Tokens}[m_Index];
68 constexpr std::size_t
pos() const noexcept
79 std::vector<lexing::token> m_Tokens;
80 std::size_t m_Index{};
101 : m_Stream{std::addressof(stream)},
102 m_Checkpoint{stream.pos()}
114 return m_Stream !=
nullptr;
119 std::size_t m_Checkpoint;
122 template <
typename State>
133 template <
typename... Args>
134 requires std::constructible_from<State, Args...>
137 : m_Transaction{stream},
138 m_State{std::in_place, std::forward<Args>(args)...}
157 constexpr std::optional<State>
take() &&
160 m_Transaction.commit();
161 return std::exchange(m_State, std::nullopt);
166 std::optional<State> m_State;
169 template <std::equality_comparable Key,
typename Value, std::
size_t length>
171 constexpr auto make_map(std::pair<Key, Value>
const (&mappings)[length])
177 explicit constexpr Map(std::pair<Key, Value>
const (&candidates)[length])
178 : m_Candidates{std::to_array(candidates)}
183 constexpr std::optional<Value> operator()(Key
const& key)
const
185 if (
auto const iter = std::ranges::find(m_Candidates, key, &std::pair<Key, Value>::first);
186 iter != std::ranges::end(m_Candidates))
195 std::array<std::pair<Key, Value>, length> m_Candidates;
198 return Map{mappings};
201 template <
typename LexerTokenClass>
205 return std::get_if<LexerTokenClass>(&stream.peek().classification);
208 template <std::equality_comparable LexerTokenClass>
210 constexpr std::optional<LexerTokenClass>
expect(
TokenStream& stream, LexerTokenClass
const& expected)
214 && *token == expected)
216 std::optional result = *token;
249 if (std::optional
const classKey = map(*keyword))
308 if (std::optional
const qualifier = map(*op))
338 struct PlaceholderWrapCandidate
345 consteval auto make_placeholder_wrap_candidates() noexcept
347 using op = lexing::operator_or_punctuator;
349 PlaceholderWrapCandidate{.open = op{
"{"}, .close = op{
"}"}},
350 PlaceholderWrapCandidate{.open = op{
"<"}, .close = op{
">"}},
351 PlaceholderWrapCandidate{.open = op{
"("}, .close = op{
")"}},
352 PlaceholderWrapCandidate{.open = op{
"`"}, .close = op{
"'"}},
355 constexpr auto projection = [](
auto const& e) {
return e.open.index(); };
356 std::ranges::sort(raw, {}, projection);
357 MIMICPP_ASSERT(raw.cend() == std::ranges::unique(raw, {}, projection).begin(),
"Fix your input!");
362 inline constexpr std::array placeholderWrapCandidates = make_placeholder_wrap_candidates();
365 constexpr char const* find_end_token(TokenStream& stream, lexing::operator_or_punctuator
const open, lexing::operator_or_punctuator
const close)
367 while (!stream.is_eof())
369 if (
auto const*
const cur = std::get_if<lexing::operator_or_punctuator>(&stream.peek().classification))
374 std::ignore = find_end_token(stream, open, close);
377 else if (close == *cur)
379 auto const*
const end = stream.peek().content.data() + stream.peek().content.size();
400 id->isSynthetic =
true;
402 if (!std::holds_alternative<lexing::operator_or_punctuator>(stream.
peek().
classification))
407 auto const begin = stream.
peek();
409 detail::placeholderWrapCandidates,
410 std::get<lexing::operator_or_punctuator>(begin.classification).index(),
412 [](
auto const& e) { return e.open.index(); });
413 if (iter == detail::placeholderWrapCandidates.cend())
421 if (
auto const*
const end = detail::find_end_token(stream, iter->open, iter->close))
423 id->content = {begin.content.data(), end};
424 return std::move(
id).take();
487 args.emplace_back(*std::move(arg));
509 *args = *std::move(argList);
517 return std::move(args).take();
531 if (std::optional
const qualifier = map(*keyword))
579 consteval auto make_simple_operator_candidates() noexcept
588 std::to_array<std::string_view>({
"->",
"->*",
","}));
590 std::array ops = std::apply(
591 [](
auto&... opTexts) {
return std::array{lexing::operator_or_punctuator{opTexts}...}; },
594 MIMICPP_ASSERT(ops.cend() == std::ranges::unique(ops).begin(),
"Fix your input!");
599 inline constexpr std::array simpleOpCandidates = make_simple_operator_candidates();
601 inline constexpr std::array doubleOpCandidates = {
602 std::tuple{lexing::operator_or_punctuator{
"("}, lexing::operator_or_punctuator{
")"}},
603 std::tuple{lexing::operator_or_punctuator{
"["}, lexing::operator_or_punctuator{
"]"}}
609 template <
bool requireOperatorKeyword = true>
616 && requireOperatorKeyword)
633 for (
auto&& [first, second] : detail::doubleOpCandidates)
636 &&
expect(stream, second))
639 .symbol = std::array{first, second}
654 std::pair symbol{*op,
false};
663 symbol.second =
true;
672 .symbol = std::pair{*op,
false}
704 *target = *std::move(base);
707 target->declarator.root.decorations.emplace_back(*std::move(op));
719 if (!std::holds_alternative<lexing::operator_or_punctuator>(stream.
peek().
classification))
724 auto const closeOp = std::invoke([&]() -> std::optional<lexing::operator_or_punctuator> {
742 auto const openToken = stream.
peek();
747 &&
id->content.starts_with(
"lambda"))
750 if (
auto const*
const end = detail::find_end_token(
752 std::get<lexing::operator_or_punctuator>(openToken.classification),
755 identifier->content = {openToken.content.data(), end};
758 return std::move(identifier).take();
776 identifier->name = *std::move(
id);
777 return std::move(identifier).take();
805 nestedId->name = *std::move(dtor);
806 return std::move(nestedId).take();
812 nestedId->name = *std::move(lambda);
813 return std::move(nestedId).take();
818 nestedId->name = *std::move(op);
823 nestedId->name = *std::move(conv);
824 return std::move(nestedId).take();
828 nestedId->name = *std::move(
id);
837 nestedId->templateArgs = *std::move(templateArgs);
840 return std::move(nestedId).
take();
853 template <
bool isFirst>
862 nestedId->name = *std::move(lambda);
866 bool requiresFunction{
false};
867 bool acceptTemplate{
false};
872 requiresFunction =
true;
873 nestedId->name = *std::move(dtor);
875 else if (std::optional opId = std::invoke([&]() -> std::optional<state::OperatorFunctionId> {
879 acceptTemplate =
true;
880 innerTransaction.
commit();
884 if constexpr (!isFirst)
895 innerTransaction.
commit();
903 nestedId->name = *std::move(opId);
908 requiresFunction =
true;
909 nestedId->name = *std::move(conv);
913 acceptTemplate =
true;
914 nestedId->name = *std::move(
id);
928 nestedId->functionDeclarator = *std::move(functionDecl);
930 else if (requiresFunction)
938 return std::move(nestedId).take();
970 if (scopes->explicitRoot)
972 return std::move(scopes).take();
978 scopes->scopes.emplace_back(*std::move(initId));
990 scopes->scopes.emplace_back(*std::move(curId));
994 return std::move(scopes).
take();
1006 id->scopes = *std::move(scopes);
1011 id->identifier = *std::move(topLevelId);
1012 return std::move(
id).take();
1015 return std::nullopt;
1024 &&
id->content.starts_with(
"__"))
1031 return std::nullopt;
1053 return std::nullopt;
1058 return {std::move(ptr).take()};
1074 return std::move(declarator).take();
1078 return std::nullopt;
1103 if (params->empty())
1108 return std::nullopt;
1111 params->emplace_back(*std::move(param));
1115 return std::move(params).
take();
1135 transaction.commit();
1149 return std::nullopt;
1155 return std::nullopt;
1160 return std::nullopt;
1167 declarator->qualifiers = *std::move(cv);
1173 declarator->params.reserve(clause->size());
1174 std::ranges::transform(
1176 std::back_inserter(declarator->params),
1177 [](
state::TypeId&
id) { return state::Recursive{std::move(id)}; });
1179 return {std::move(declarator).take()};
1186 auto& root = declarator->root;
1190 root.decorations.emplace_back(*std::move(op));
1200 root.nested.emplace(std::move(layer->root));
1201 nestedTransaction.commit();
1207 root.function.emplace(*std::move(params));
1212 root.arrays.emplace_back(*std::move(arrayDecl));
1215 if (root.decorations.empty()
1218 && root.arrays.empty())
1220 return std::nullopt;
1223 return {std::move(declarator).take()};
1229 consteval auto make_builtin_type_candidates() noexcept
1231 std::array types = std::apply(
1232 [](
auto&... keyword) {
return std::array{
lexing::keyword{keyword}...}; },
1233 lexing::texts::typeKeywords);
1234 std::ranges::sort(types, {}, &lexing::keyword::index);
1235 MIMICPP_ASSERT(types.cend() == std::ranges::unique(types).begin(),
"Fix your input!");
1240 inline constexpr std::array builtinTypeCandidates = make_builtin_type_candidates();
1249 std::optional<state::QualifiedId> qualifiedType{};
1250 std::optional<state::BuiltinType> builtinType{};
1251 std::optional<state::TypeKey> typeKey{};
1270 if (!typeId->qualifications.apply(*cv))
1280 && std::ranges::binary_search(detail::builtinTypeCandidates, keyword->index(), {}, &
lexing::keyword::index))
1282 if (!(builtinType ? *builtinType : builtinType.emplace()).try_apply(*keyword))
1293 if (!qualifiedType && !builtinType)
1299 qualifiedType = std::move(qualifiedId);
1311 qualifiedType->typeKey = std::move(typeKey);
1312 typeId->base = *std::move(qualifiedType);
1313 return std::move(typeId).take();
1320 typeId->base = *std::move(builtinType);
1321 return std::move(typeId).take();
1324 return std::nullopt;
1335 return std::nullopt;
1338 *
id = *std::move(base);
1342 id->declarator = *std::move(declarator);
1345 return std::move(
id).take();
1360 id->returnType = std::move(returnType);
1361 id->identifier = *std::move(identifier);
1362 id->identifier.identifier.functionDeclarator = *std::move(declarator);
1364 return std::move(
id).take();
1370 else if (
auto*
const qualifiedId = std::get_if<state::QualifiedId>(&returnType->base))
1372 id->identifier = std::move(*qualifiedId);
1373 id->identifier.identifier.functionDeclarator = std::move(returnType->declarator.root.function);
1375 return std::move(
id).take();
1379 return std::nullopt;
1396 return std::nullopt;
1407 || (text.ends_with(
']')
1414 return std::nullopt;
#define MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES
Definition Config.hpp:93
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:54
Definition Parser.hpp:124
StateGuard & operator=(StateGuard const &)=delete
constexpr std::optional< State > take() &&
Definition Parser.hpp:157
StateGuard & operator=(StateGuard &&)=delete
constexpr State * operator->() noexcept
Definition Parser.hpp:150
constexpr State & operator*() noexcept
Definition Parser.hpp:143
StateGuard(StateGuard &&)=delete
constexpr StateGuard(TokenStream &stream, Args &&... args)
Definition Parser.hpp:136
StateGuard(StateGuard const &)=delete
constexpr bool is_eof() const noexcept
Definition Parser.hpp:49
constexpr void consume()
Definition Parser.hpp:61
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES TokenStream(lexing::NameLexer &lexer) noexcept
Definition Parser.hpp:34
constexpr std::size_t pos() const noexcept
Definition Parser.hpp:68
constexpr void seek(util::pass_key< Transaction > const, std::size_t const pos)
Definition Parser.hpp:73
constexpr lexing::token const & peek() const
Definition Parser.hpp:55
Transaction(Transaction &&)=delete
Transaction & operator=(Transaction const &)=delete
constexpr bool is_active() const noexcept
Definition Parser.hpp:112
constexpr ~Transaction() noexcept
Definition Parser.hpp:91
constexpr void commit() noexcept
Definition Parser.hpp:106
constexpr Transaction(TokenStream &stream) noexcept
Definition Parser.hpp:100
Transaction(Transaction const &)=delete
Transaction & operator=(Transaction &&)=delete
Definition ParserState.hpp:31
std::array constexpr incOrDec
Definition Lexer.hpp:65
std::array constexpr assignment
Definition Lexer.hpp:64
std::array constexpr logical
Definition Lexer.hpp:68
std::array constexpr arithmetic
Definition Lexer.hpp:66
std::array constexpr comparison
Definition Lexer.hpp:63
std::array constexpr bitArithmetic
Definition Lexer.hpp:67
@ id_enum_class
Definition ParserState.hpp:82
@ id_enum
Definition ParserState.hpp:81
@ id_enum_struct
Definition ParserState.hpp:83
std::vector< TemplateArgument > TemplateArgumentList
Definition ParserState.hpp:149
@ id_ref
Definition ParserState.hpp:119
@ id_refref
Definition ParserState.hpp:120
@ id_struct
Definition ParserState.hpp:74
@ id_class
Definition ParserState.hpp:73
@ id_volatile
Definition ParserState.hpp:89
@ id_const
Definition ParserState.hpp:88
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< std::vector< state::TypeId > > parse_parameter_declaration_clause(TokenStream &stream)
Definition Parser.hpp:1093
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::OperatorFunctionId > parse_operator_function_id(TokenStream &stream)
Definition Parser.hpp:611
constexpr auto make_map(std::pair< Key, Value > const (&mappings)[length])
Definition Parser.hpp:171
constexpr std::optional< state::ConstantExpression > parse_constant_expression(TokenStream &stream)
Definition Parser.hpp:325
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::LambdaFunctionId > parse_lambda_function_id(TokenStream &stream)
Definition Parser.hpp:715
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES void ignore_function_attribute(TokenStream &stream)
Definition Parser.hpp:1118
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::DestructorFunctionId > parse_destructor_function_id(TokenStream &stream)
Definition Parser.hpp:768
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::FunctionId > parse_function(TokenStream &stream)
Definition Parser.hpp:1349
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::AbstractDeclarator > parse_abstract_declarator(TokenStream &stream)
Definition Parser.hpp:1183
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::TemplateArgumentList > parse_template_argument_list(TokenStream &stream)
Definition Parser.hpp:465
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::TypeId > parse_type_id(TokenStream &stream)
Definition Parser.hpp:1329
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::ConversionFunctionId > parse_conversion_function_id(TokenStream &stream)
Definition Parser.hpp:689
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::UnqualifiedId > parse_nested_id(TokenStream &stream)
Definition Parser.hpp:855
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::FunctionDeclarator > parse_parameters_and_qualifiers(TokenStream &stream)
Definition Parser.hpp:1143
constexpr std::optional< state::EnumKey > parse_enum_key(TokenStream &stream)
Definition Parser.hpp:261
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::CVQualifierSeq > parse_cv_qualifier_seq(TokenStream &stream)
Definition Parser.hpp:544
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::TemplateArgument > parse_template_argument(TokenStream &stream)
Definition Parser.hpp:447
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::UnqualifiedId > parse_unqualified_id(TokenStream &stream)
Definition Parser.hpp:798
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::ScopeSequence > parse_nested_name_specifier(TokenStream &stream)
Definition Parser.hpp:962
constexpr std::optional< state::TypeKey > parse_type_key(TokenStream &stream)
Definition Parser.hpp:282
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::QualifiedId > parse_qualified_id(TokenStream &stream)
Definition Parser.hpp:1000
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::PtrOperator > parse_ptr_operator(TokenStream &stream)
Definition Parser.hpp:1037
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::CallConvention > parse_call_convention(TokenStream &stream)
Definition Parser.hpp:1019
constexpr std::optional< state::RefQualifier > parse_ref_qualifier(TokenStream &stream)
Definition Parser.hpp:299
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::TypeId > parse_type_specifier_seq(TokenStream &stream)
Definition Parser.hpp:1245
constexpr std::optional< state::Identifier > parse_identifier(TokenStream &stream)
Definition Parser.hpp:433
constexpr std::optional< state::CVQualifier > parse_cv_qualifier(TokenStream &stream)
Definition Parser.hpp:522
constexpr std::optional< state::Identifier > parse_synthetic_id(TokenStream &stream)
Definition Parser.hpp:397
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::TypeId > parse_parameter_declaration(TokenStream &stream)
Definition Parser.hpp:1083
constexpr std::optional< state::ClassKey > parse_class_key(TokenStream &stream)
Definition Parser.hpp:239
constexpr std::optional< LexerTokenClass > expect(TokenStream &stream, LexerTokenClass const &expected)
Definition Parser.hpp:210
constexpr std::optional< state::ArrayDeclarator > parse_array_declarator(TokenStream &stream)
Definition Parser.hpp:1066
constexpr LexerTokenClass const * peek_if(TokenStream const &stream) noexcept
Definition Parser.hpp:203
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< state::TemplateArgumentList > parse_template_clause(TokenStream &stream)
Definition Parser.hpp:498
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< parsing::state::FunctionId > parse_function(std::string_view const text)
Definition Parser.hpp:1399
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< parsing::state::TypeId > parse_type(std::string_view const text)
Definition Parser.hpp:1385
constexpr std::array< T, firstN+secondN > concat_arrays(std::array< T, firstN > const &first, std::array< T, secondN > const &second)
Concatenates the given arrays by copying all elements into a new array.
Definition Algorithm.hpp:218
void unreachable()
Invokes undefined behavior.
Definition C++23Backports.hpp:40
constexpr detail::binary_find_fn binary_find
Finds the specified value within the container and returns an iterator pointing to it....
Definition Algorithm.hpp:361
constexpr std::ptrdiff_t index() const noexcept
Definition Lexer.hpp:147
constexpr std::ptrdiff_t index() const noexcept
Definition Lexer.hpp:187
token_class classification
Definition Lexer.hpp:232
Definition ParserState.hpp:93
bool isVolatile
Definition ParserState.hpp:95
bool isConst
Definition ParserState.hpp:94
Definition ParserState.hpp:248
Definition ParserState.hpp:176
Definition ParserState.hpp:126
Definition ParserState.hpp:152
std::variant< lexing::operator_or_punctuator, std::pair< lexing::keyword, bool >, std::array< lexing::operator_or_punctuator, 2u > > Symbol
Definition ParserState.hpp:153
Definition ParserState.hpp:266
Definition ParserState.hpp:417
A helper type that enables fine-grained access control to specific functions without using friend dec...
Definition PassKey.hpp:29