option.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2024 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_DSL_OPTION_HPP_INCLUDED
5 #define LEXY_DSL_OPTION_HPP_INCLUDED
6 
7 #include <lexy/dsl/base.hpp>
8 #include <lexy/dsl/branch.hpp>
9 #include <lexy/dsl/recover.hpp>
10 
11 namespace lexy
12 {
13 // An optional type is something that has the following:
14 // * a default constructor: this means we can actually construct it from our `nullopt`
15 // * a dereference operator: this means that it actually contains something else
16 // * a contextual conversion to bool: this means that it might be "false" (i.e. empty)
17 //
18 // This definition should work:
19 // * it excludes all default constructible types that are convertible to bool (e.g. integers...)
20 // * it includes pointers, which is ok
21 // * it includes `std::optional` and all non-std implementations of it
22 template <typename T>
23 using _detect_optional_like = decltype(T(), *LEXY_DECLVAL(T&), !LEXY_DECLVAL(const T&));
24 
25 struct nullopt
26 {
27  template <typename T, typename = _detect_optional_like<T>>
28  constexpr operator T() const
29  {
30  return T();
31  }
32 };
33 } // namespace lexy
34 
35 namespace lexyd
36 {
38 {
39  template <typename NextParser>
40  struct p
41  {
42  template <typename Context, typename Reader, typename... Args>
43  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
44  {
45  return NextParser::parse(context, reader, LEXY_FWD(args)..., lexy::nullopt{});
46  }
47  };
48 };
49 
50 constexpr auto nullopt = _nullopt{};
51 } // namespace lexyd
52 
53 namespace lexyd
54 {
55 template <typename Branch>
56 struct _opt : rule_base
57 {
58  template <typename NextParser>
59  struct p
60  {
61  template <typename Context, typename Reader, typename... Args>
62  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
63  {
65  if (branch.try_parse(context.control_block, reader))
66  // We take the branch.
67  return branch.template finish<NextParser>(context, reader, LEXY_FWD(args)...);
68  else
69  {
70  // We don't take the branch and produce a nullopt.
71  branch.cancel(context);
72  return NextParser::parse(context, reader, LEXY_FWD(args)..., lexy::nullopt{});
73  }
74  }
75  };
76 };
77 
80 template <typename Rule>
81 constexpr auto opt(Rule)
82 {
83  LEXY_REQUIRE_BRANCH_RULE(Rule, "opt()");
84  if constexpr (lexy::is_unconditional_branch_rule<Rule>)
85  // Branch is always taken, so don't wrap in opt().
86  return Rule{};
87  else
88  return _opt<Rule>{};
89 }
90 } // namespace lexyd
91 
92 namespace lexyd
93 {
94 template <typename Term, typename Rule>
95 struct _optt : rule_base
96 {
97  template <typename NextParser>
98  struct p
99  {
100  template <typename Context, typename Reader, typename... Args>
101  LEXY_PARSER_FUNC static bool parse(Context& context, Reader& reader, Args&&... args)
102  {
103  // Try to parse the terminator.
105  if (term.try_parse(context.control_block, reader))
106  // We had the terminator, so produce nullopt.
107  return term.template finish<NextParser>(context, reader, LEXY_FWD(args)...,
108  lexy::nullopt{});
109  term.cancel(context);
110 
111  // We didn't have the terminator, so we parse the rule.
112  using parser = lexy::parser_for<Rule, NextParser>;
113  return parser::parse(context, reader, LEXY_FWD(args)...);
114  }
115  };
116 };
117 } // namespace lexyd
118 
119 #endif // LEXY_DSL_OPTION_HPP_INCLUDED
120 
lexy::branch_parser_for
typename BranchRule::template bp< Reader > branch_parser_for
Definition: dsl/base.hpp:116
lexyd::_optt::p
Definition: option.hpp:98
lexyd::_nullopt::p
Definition: option.hpp:40
lexy::nullopt
Definition: option.hpp:25
LEXY_FWD
#define LEXY_FWD(...)
Definition: config.hpp:30
lexy
Definition: any_ref.hpp:12
LEXY_REQUIRE_BRANCH_RULE
#define LEXY_REQUIRE_BRANCH_RULE(Rule, Name)
Definition: grammar.hpp:73
lexyd::_opt::p::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: option.hpp:62
lexyd::nullopt
constexpr auto nullopt
Definition: option.hpp:50
lexy::parse
constexpr auto parse(const Input &input, const ErrorCallback &callback)
Parses the production into a value, invoking the callback on error.
Definition: parse.hpp:171
recover.hpp
lexyd::rule_base
Definition: grammar.hpp:17
lexyd::_opt::p
Definition: option.hpp:59
lexyd::_optt::p::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: option.hpp:101
LEXY_PARSER_FUNC
#define LEXY_PARSER_FUNC
Definition: dsl/base.hpp:108
base.hpp
lexyd::_nullopt::p::parse
static LEXY_PARSER_FUNC bool parse(Context &context, Reader &reader, Args &&... args)
Definition: option.hpp:43
lexyd::_optt
Definition: option.hpp:95
lexy::parser_for
typename Rule::template p< NextParser > parser_for
Definition: dsl/base.hpp:113
lexyd::opt
constexpr auto opt(Rule)
Definition: option.hpp:81
LEXY_DECLVAL
#define LEXY_DECLVAL(...)
Definition: config.hpp:32
lexyd::_nullopt
Definition: option.hpp:37
lexyd::_opt
Definition: option.hpp:56
lexyd
Definition: trace.hpp:22
branch.hpp
lexy::_detect_optional_like
decltype(T(), *LEXY_DECLVAL(T &), !LEXY_DECLVAL(const T &)) _detect_optional_like
Definition: option.hpp:23


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Nov 1 2024 02:20:51