token.hpp
Go to the documentation of this file.
1 // Copyright (C) 2020-2023 Jonathan Müller and lexy contributors
2 // SPDX-License-Identifier: BSL-1.0
3 
4 #ifndef LEXY_TOKEN_HPP_INCLUDED
5 #define LEXY_TOKEN_HPP_INCLUDED
6 
7 #include <climits>
8 #include <cstdint>
10 #include <lexy/_detail/config.hpp>
11 #include <lexy/_detail/detect.hpp>
13 #include <lexy/grammar.hpp>
14 #include <lexy/lexeme.hpp>
15 
16 namespace lexy
17 {
18 template <typename TokenKind, typename... Tokens>
19 struct _tk_map
20 {
21  TokenKind _data[sizeof...(Tokens)];
22 
23  template <std::size_t... Idx>
25  TokenKind new_kind)
26  // Add new kind at the end.
27  : _data{data[Idx]..., new_kind}
28  {}
29 
30  template <TokenKind Kind, typename Token>
31  LEXY_CONSTEVAL auto map(Token) const
32  {
33  static_assert(lexy::is_token_rule<Token>, "cannot map non-token to token kind");
34  return _tk_map<TokenKind, Tokens..., Token>(lexy::_detail::index_sequence_for<Tokens...>{},
35  _data, Kind);
36  }
37 
38  template <typename Token>
39  LEXY_CONSTEVAL auto lookup(Token) const
40  {
41  constexpr auto idx = [] {
42  // There is an easier way to do it via fold expressions but clang 6 generates a bogus
43  // warning about sequence points.
44  // As such, we do the less fancy version of looking for the index in an array.
45  bool is_same[]
46  = {std::is_same_v<typename Token::token_type, typename Tokens::token_type>...};
47 
48  for (std::size_t idx = 0; idx != sizeof...(Tokens); ++idx)
49  if (is_same[idx])
50  return idx;
51 
52  return sizeof...(Tokens);
53  }();
54  if constexpr (idx == sizeof...(Tokens))
55  return unknown_token_kind;
56  else
57  return _data[idx];
58  }
59 };
60 
62 {
63  template <typename Token>
64  static LEXY_CONSTEVAL auto lookup(Token)
65  {
66  return unknown_token_kind;
67  }
68 
69  template <auto TokenKind, typename Token>
70  LEXY_CONSTEVAL auto map(Token) const
71  {
72  static_assert(lexy::is_token_rule<Token>, "cannot map non-token to token kind");
74  nullptr, TokenKind);
75  }
76 };
77 
78 inline constexpr auto token_kind_map = _tk_map_empty{};
79 
81 template <typename TokenKind>
83 
84 // Prevent user-defined specialization for void.
85 template <>
86 inline constexpr auto token_kind_map_for<void> = token_kind_map;
87 } // namespace lexy
88 
89 namespace lexy
90 {
91 template <typename TokenKind>
92 using _detect_token_kind_name = decltype(token_kind_name(TokenKind{}));
93 
94 template <typename TokenRule>
95 constexpr auto _has_special_token_kind = [] {
96  using kind = LEXY_DECAY_DECLTYPE(lexy::token_kind_of<TokenRule>);
97  return !std::is_same_v<kind, lexy::predefined_token_kind> && std::is_enum_v<kind>;
98 }();
99 
101 template <typename TokenKind = void>
103 {
104  static_assert(std::is_void_v<TokenKind> || std::is_enum_v<TokenKind>,
105  "invalid type for TokenKind");
107 
108  template <typename T>
109  static constexpr bool _is_compatible_kind_type()
110  {
111  using type = std::remove_cv_t<T>;
112  if constexpr (std::is_same_v<type, lexy::predefined_token_kind>)
113  // Always compatible.
114  return true;
115  else if constexpr (std::is_void_v<TokenKind>)
116  // We neeed an integer for our token kind.
117  return std::is_integral_v<T>;
118  else
119  // We need the same enumeration type.
120  return std::is_same_v<type, TokenKind>;
121  }
122 
123 public:
124  //=== constructors ===//
126  constexpr token_kind() noexcept : token_kind(unknown_token_kind) {}
127 
129  constexpr token_kind(predefined_token_kind value) noexcept : _value(value) {}
130 
132  constexpr token_kind(_underlying_type value) noexcept
133  : _value(static_cast<std::uint_least16_t>(value))
134  {
137  }
138 
140  template <typename TokenRule, typename = std::enable_if_t<lexy::is_token_rule<TokenRule>>>
141  constexpr token_kind(TokenRule) noexcept
142  // We initialize it according to the external mapping.
143  : token_kind(token_kind_map_for<TokenKind>.lookup(TokenRule{}))
144  {
145  // If unknown, override it by internal mapping.
146  if (!*this)
147  {
148  constexpr auto token_rule_kind = lexy::token_kind_of<TokenRule>;
149  if constexpr (_is_compatible_kind_type<decltype(token_rule_kind)>())
150  {
151  // The token has an associated kind of the same type.
152  *this = token_kind(token_rule_kind);
153  }
154  }
155  }
156 
157  //=== access ===//
158  constexpr explicit operator bool() const noexcept
159  {
160  return _value != unknown_token_kind;
161  }
162 
163  constexpr bool is_predefined() const noexcept
164  {
166  }
167 
168  constexpr bool ignore_if_empty() const noexcept
169  {
172  }
173 
174  constexpr const char* name() const noexcept
175  {
176  if (is_predefined())
177  return _kind_name(static_cast<predefined_token_kind>(_value));
178  else if constexpr (lexy::_detail::is_detected<_detect_token_kind_name, TokenKind>)
179  return token_kind_name(get()); // ADL
180  else
181  // We only have a generic name.
182  return "token";
183  }
184 
185  constexpr _underlying_type get() const noexcept
186  {
187  return static_cast<_underlying_type>(_value);
188  }
189 
190  //=== comparision ===//
191  friend constexpr bool operator==(token_kind lhs, token_kind rhs) noexcept
192  {
193  return lhs._value == rhs._value;
194  }
195  friend constexpr bool operator!=(token_kind lhs, token_kind rhs) noexcept
196  {
197  return lhs._value != rhs._value;
198  }
199 
200  //=== raw access ===//
201  static constexpr std::uint_least16_t to_raw(token_kind<TokenKind> kind) noexcept
202  {
203  return kind._value;
204  }
205  static constexpr token_kind<TokenKind> from_raw(std::uint_least16_t kind) noexcept
206  {
207  return token_kind<TokenKind>(kind);
208  }
209 
210 private:
211  constexpr explicit token_kind(std::uint_least16_t kind) noexcept : _value(kind) {}
212 
213  std::uint_least16_t _value;
214 };
215 
216 template <typename TokenKind, typename = std::enable_if_t<std::is_integral_v<TokenKind>>>
217 token_kind(TokenKind) -> token_kind<void>;
218 template <typename TokenKind, typename = std::enable_if_t<std::is_enum_v<TokenKind>>>
219 token_kind(TokenKind) -> token_kind<TokenKind>;
220 template <typename TokenRule, typename = std::enable_if_t<_has_special_token_kind<TokenRule>>>
221 token_kind(TokenRule) -> token_kind<LEXY_DECAY_DECLTYPE(lexy::token_kind_of<TokenRule>)>;
222 } // namespace lexy
223 
224 namespace lexy
225 {
227 template <typename Reader, typename TokenKind = void>
228 class token
229 {
230 public:
231  using encoding = typename Reader::encoding;
232  using char_type = typename encoding::char_type;
233  using iterator = typename Reader::iterator;
234 
235  explicit constexpr token(token_kind<TokenKind> kind, lexy::lexeme<Reader> lex) noexcept
236  : _lexeme(lex), _kind(kind)
237  {
238  LEXY_PRECONDITION(lex.begin() != iterator());
239  }
240  explicit constexpr token(token_kind<TokenKind> kind, iterator begin, iterator end) noexcept
242  {}
243 
244  constexpr token_kind<TokenKind> kind() const noexcept
245  {
246  return _kind;
247  }
248 
249  constexpr const char* name() const noexcept
250  {
251  return _kind.name();
252  }
253 
254  constexpr iterator position() const noexcept
255  {
256  return _lexeme.begin();
257  }
258 
259  constexpr auto lexeme() const noexcept
260  {
261  return _lexeme;
262  }
263 
264 private:
267 };
268 
269 template <typename TokenKind, typename Reader>
271 template <typename TokenKind, typename Reader,
272  typename = std::enable_if_t<std::is_integral_v<TokenKind>>>
274 template <typename TokenKind, typename Reader,
275  typename = std::enable_if_t<std::is_enum_v<TokenKind>>>
277 template <typename TokenRule, typename Reader,
278  typename = std::enable_if_t<_has_special_token_kind<TokenRule>>>
279 token(TokenRule, lexy::lexeme<Reader>)
280  -> token<Reader, LEXY_DECAY_DECLTYPE(lexy::token_kind_of<TokenRule>)>;
281 
282 template <typename Input, typename TokenKind = void>
284 } // namespace lexy
285 
286 #endif // LEXY_TOKEN_HPP_INCLUDED
287 
lexy::token_kind::_is_compatible_kind_type
static constexpr bool _is_compatible_kind_type()
Definition: token.hpp:109
detect.hpp
LEXY_CONSTEVAL
#define LEXY_CONSTEVAL
Definition: config.hpp:90
lexy::unknown_token_kind
@ unknown_token_kind
Definition: grammar.hpp:75
lexy::token::token
constexpr token(token_kind< TokenKind > kind, iterator begin, iterator end) noexcept
Definition: token.hpp:240
lexy::_detail::index_sequence_for
make_index_sequence< sizeof...(T)> index_sequence_for
Definition: integer_sequence.hpp:60
lexy::token_kind::token_kind
constexpr token_kind(TokenRule) noexcept
Creates the token kind of a token rule.
Definition: token.hpp:141
lexy::token::iterator
typename Reader::iterator iterator
Definition: token.hpp:233
magic_enum::char_type
string_view::value_type char_type
Definition: magic_enum.hpp:145
lexy::token::lexeme
constexpr auto lexeme() const noexcept
Definition: token.hpp:259
config.hpp
lexy::token_kind::ignore_if_empty
constexpr bool ignore_if_empty() const noexcept
Definition: token.hpp:168
lexy::token_kind
token_kind(TokenKind) -> token_kind< void >
lexy::token_kind::token_kind
constexpr token_kind(_underlying_type value) noexcept
Creates the token kind with the specified value.
Definition: token.hpp:132
lexy::token
A parsed token, i.e. its kind and its lexeme.
Definition: token.hpp:228
lexy::token
token(token_kind< TokenKind >, lexy::lexeme< Reader >) -> token< Reader, TokenKind >
lexy::_detail::type_or
std::conditional_t< std::is_void_v< T >, Fallback, T > type_or
Definition: config.hpp:56
lexy::_tk_map_empty
Definition: token.hpp:61
lexy::token::encoding
typename Reader::encoding encoding
Definition: token.hpp:231
lexy::_tk_map::_data
TokenKind _data[sizeof...(Tokens)]
Definition: token.hpp:21
lexy::token_kind_map_for
constexpr auto token_kind_map_for
A mapping of token rule to token kind; specialize for your own kinds.
Definition: token.hpp:82
SafeAny::details::is_same
constexpr bool is_same()
Definition: convert_impl.hpp:58
lexy::_detail::integer_sequence
Definition: integer_sequence.hpp:12
lexy
Definition: any_ref.hpp:12
lexy::token_kind::token_kind
constexpr token_kind(predefined_token_kind value) noexcept
Creates a predefined token kind.
Definition: token.hpp:129
LEXY_PRECONDITION
#define LEXY_PRECONDITION(Expr)
Definition: assert.hpp:36
lexy::predefined_token_kind
predefined_token_kind
Definition: grammar.hpp:73
lexy::token_kind_map
constexpr auto token_kind_map
Definition: token.hpp:78
cx::end
constexpr auto end(const C &c) -> decltype(c.end())
Definition: wildcards.hpp:686
lexy::_kind_name
constexpr const char * _kind_name(predefined_token_kind kind) noexcept
Definition: grammar.hpp:91
lexy::_tk_map
Definition: token.hpp:19
grammar.hpp
lexy::token_kind::token_kind
constexpr token_kind(std::uint_least16_t kind) noexcept
Definition: token.hpp:211
lexy::token_kind::get
constexpr _underlying_type get() const noexcept
Definition: token.hpp:185
lexy::token::position
constexpr iterator position() const noexcept
Definition: token.hpp:254
lexy::_tk_map_empty::map
LEXY_CONSTEVAL auto map(Token) const
Definition: token.hpp:70
lexy::token::kind
constexpr token_kind< TokenKind > kind() const noexcept
Definition: token.hpp:244
lexy::whitespace_token_kind
@ whitespace_token_kind
Definition: grammar.hpp:78
lexy::token_kind
What sort of token it is.
Definition: token.hpp:102
lexeme.hpp
lexy::_tk_map_empty::lookup
static LEXY_CONSTEVAL auto lookup(Token)
Definition: token.hpp:64
lexy::token_kind::operator==
constexpr friend bool operator==(token_kind lhs, token_kind rhs) noexcept
Definition: token.hpp:191
lexy::token_kind::from_raw
static constexpr token_kind< TokenKind > from_raw(std::uint_least16_t kind) noexcept
Definition: token.hpp:205
LEXY_DECAY_DECLTYPE
#define LEXY_DECAY_DECLTYPE(...)
Definition: config.hpp:26
assert.hpp
lexy::error_token_kind
@ error_token_kind
Definition: grammar.hpp:77
lexy::token::_lexeme
lexy::lexeme< Reader > _lexeme
Definition: token.hpp:265
lexy::_tk_map::lookup
LEXY_CONSTEVAL auto lookup(Token) const
Definition: token.hpp:39
integer_sequence.hpp
cx::begin
constexpr auto begin(const C &c) -> decltype(c.begin())
Definition: wildcards.hpp:661
lexy::_has_special_token_kind
constexpr auto _has_special_token_kind
Definition: token.hpp:95
lexy::token_kind::token_kind
constexpr token_kind() noexcept
Creates an unknown token kind.
Definition: token.hpp:126
lexy::token::_kind
token_kind< TokenKind > _kind
Definition: token.hpp:266
lexy::token_kind_map_for< void >
constexpr auto token_kind_map_for< void >
Definition: token.hpp:86
lexy::token_kind::name
constexpr const char * name() const noexcept
Definition: token.hpp:174
lexy::_tk_map::map
LEXY_CONSTEVAL auto map(Token) const
Definition: token.hpp:31
lexy::lexeme
Definition: lexeme.hpp:16
lexy::token_kind::operator!=
constexpr friend bool operator!=(token_kind lhs, token_kind rhs) noexcept
Definition: token.hpp:195
lexy::token::char_type
typename encoding::char_type char_type
Definition: token.hpp:232
lexy::_tk_map::_tk_map
LEXY_CONSTEVAL _tk_map(lexy::_detail::index_sequence< Idx... >, const TokenKind *data, TokenKind new_kind)
Definition: token.hpp:24
lexy::_smallest_predefined_token_kind
@ _smallest_predefined_token_kind
Definition: grammar.hpp:88
lexy::token_kind::_value
std::uint_least16_t _value
Definition: token.hpp:213
lexy::_detect_token_kind_name
decltype(token_kind_name(TokenKind{})) _detect_token_kind_name
Definition: token.hpp:92
lexy::token::token
constexpr token(token_kind< TokenKind > kind, lexy::lexeme< Reader > lex) noexcept
Definition: token.hpp:235
lexy::token::name
constexpr const char * name() const noexcept
Definition: token.hpp:249
lexy::token_kind::to_raw
static constexpr std::uint_least16_t to_raw(token_kind< TokenKind > kind) noexcept
Definition: token.hpp:201
lexy::token_kind< void >::_underlying_type
lexy::_detail::type_or< void, int > _underlying_type
Definition: token.hpp:106
lexy::token_kind::is_predefined
constexpr bool is_predefined() const noexcept
Definition: token.hpp:163


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:08