token.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_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 TokenRule>
92 constexpr auto _has_special_token_kind = [] {
93  using kind = LEXY_DECAY_DECLTYPE(lexy::token_kind_of<TokenRule>);
94  return !std::is_same_v<kind, lexy::predefined_token_kind> && std::is_enum_v<kind>;
95 }();
96 
98 template <typename TokenKind = void>
100 {
101  static_assert(std::is_void_v<TokenKind> || std::is_enum_v<TokenKind>,
102  "invalid type for TokenKind");
104 
105  template <typename T>
106  static constexpr bool _is_compatible_kind_type()
107  {
108  using type = std::remove_cv_t<T>;
109  if constexpr (std::is_same_v<type, lexy::predefined_token_kind>)
110  // Always compatible.
111  return true;
112  else if constexpr (std::is_void_v<TokenKind>)
113  // We neeed an integer for our token kind.
114  return std::is_integral_v<T>;
115  else
116  // We need the same enumeration type.
117  return std::is_same_v<type, TokenKind>;
118  }
119 
120 public:
121  //=== constructors ===//
123  constexpr token_kind() noexcept : token_kind(unknown_token_kind) {}
124 
126  constexpr token_kind(predefined_token_kind value) noexcept : _value(value) {}
127 
129  constexpr token_kind(_underlying_type value) noexcept
130  : _value(static_cast<std::uint_least16_t>(value))
131  {
134  }
135 
137  template <typename TokenRule, typename = std::enable_if_t<lexy::is_token_rule<TokenRule>>>
138  constexpr token_kind(TokenRule) noexcept
139  // We initialize it according to the external mapping.
140  : token_kind(token_kind_map_for<TokenKind>.lookup(TokenRule{}))
141  {
142  // If unknown, override it by internal mapping.
143  if (!*this)
144  {
145  constexpr auto token_rule_kind = lexy::token_kind_of<TokenRule>;
146  if constexpr (_is_compatible_kind_type<decltype(token_rule_kind)>())
147  {
148  // The token has an associated kind of the same type.
149  *this = token_kind(token_rule_kind);
150  }
151  }
152  }
153 
154  //=== access ===//
155  constexpr explicit operator bool() const noexcept
156  {
157  return _value != unknown_token_kind;
158  }
159 
160  constexpr bool is_predefined() const noexcept
161  {
163  }
164 
165  constexpr bool ignore_if_empty() const noexcept
166  {
169  }
170 
171  constexpr const char* name() const noexcept
172  {
173  if (is_predefined())
174  return token_kind_name(static_cast<predefined_token_kind>(_value));
175  else
176  return token_kind_name(get()); // ADL
177  }
178  friend constexpr const char* token_kind_name(token_kind kind) noexcept
179  {
180  return kind.name();
181  }
182 
183  constexpr _underlying_type get() const noexcept
184  {
185  return static_cast<_underlying_type>(_value);
186  }
187 
188  //=== comparision ===//
189  friend constexpr bool operator==(token_kind lhs, token_kind rhs) noexcept
190  {
191  return lhs._value == rhs._value;
192  }
193  friend constexpr bool operator!=(token_kind lhs, token_kind rhs) noexcept
194  {
195  return lhs._value != rhs._value;
196  }
197 
198  //=== raw access ===//
199  static constexpr std::uint_least16_t to_raw(token_kind<TokenKind> kind) noexcept
200  {
201  return kind._value;
202  }
203  static constexpr token_kind<TokenKind> from_raw(std::uint_least16_t kind) noexcept
204  {
205  return token_kind<TokenKind>(kind);
206  }
207 
208 private:
209  constexpr explicit token_kind(std::uint_least16_t kind) noexcept : _value(kind) {}
210 
211  std::uint_least16_t _value;
212 };
213 
214 template <typename TokenKind, typename = std::enable_if_t<std::is_integral_v<TokenKind>>>
215 token_kind(TokenKind) -> token_kind<void>;
216 template <typename TokenKind, typename = std::enable_if_t<std::is_enum_v<TokenKind>>>
217 token_kind(TokenKind) -> token_kind<TokenKind>;
218 template <typename TokenRule, typename = std::enable_if_t<_has_special_token_kind<TokenRule>>>
219 token_kind(TokenRule) -> token_kind<LEXY_DECAY_DECLTYPE(lexy::token_kind_of<TokenRule>)>;
220 } // namespace lexy
221 
222 namespace lexy
223 {
225 template <typename Reader, typename TokenKind = void>
226 class token
227 {
228 public:
229  using encoding = typename Reader::encoding;
230  using char_type = typename encoding::char_type;
231  using iterator = typename Reader::iterator;
232 
233  explicit constexpr token(token_kind<TokenKind> kind, lexy::lexeme<Reader> lex) noexcept
234  : _lexeme(lex), _kind(kind)
235  {
236  LEXY_PRECONDITION(lex.begin() != iterator());
237  }
238  explicit constexpr token(token_kind<TokenKind> kind, iterator begin, iterator end) noexcept
240  {}
241 
242  constexpr token_kind<TokenKind> kind() const noexcept
243  {
244  return _kind;
245  }
246 
247  constexpr const char* name() const noexcept
248  {
249  return _kind.name();
250  }
251 
252  constexpr iterator position() const noexcept
253  {
254  return _lexeme.begin();
255  }
256 
257  constexpr auto lexeme() const noexcept
258  {
259  return _lexeme;
260  }
261 
262 private:
265 };
266 
267 template <typename TokenKind, typename Reader>
269 template <typename TokenKind, typename Reader,
270  typename = std::enable_if_t<std::is_integral_v<TokenKind>>>
272 template <typename TokenKind, typename Reader,
273  typename = std::enable_if_t<std::is_enum_v<TokenKind>>>
275 template <typename TokenRule, typename Reader,
276  typename = std::enable_if_t<_has_special_token_kind<TokenRule>>>
277 token(TokenRule, lexy::lexeme<Reader>)
278  -> token<Reader, LEXY_DECAY_DECLTYPE(lexy::token_kind_of<TokenRule>)>;
279 
280 template <typename Input, typename TokenKind = void>
282 } // namespace lexy
283 
284 #endif // LEXY_TOKEN_HPP_INCLUDED
285 
lexy::token_kind::_is_compatible_kind_type
static constexpr bool _is_compatible_kind_type()
Definition: token.hpp:106
detect.hpp
LEXY_CONSTEVAL
#define LEXY_CONSTEVAL
Definition: config.hpp:98
lexy::unknown_token_kind
@ unknown_token_kind
Definition: grammar.hpp:84
lexy::token::token
constexpr token(token_kind< TokenKind > kind, iterator begin, iterator end) noexcept
Definition: token.hpp:238
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:138
lexy::token::iterator
typename Reader::iterator iterator
Definition: token.hpp:231
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:257
config.hpp
lexy::token_kind::ignore_if_empty
constexpr bool ignore_if_empty() const noexcept
Definition: token.hpp:165
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:129
lexy::token
A parsed token, i.e. its kind and its lexeme.
Definition: token.hpp:226
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:64
lexy::_tk_map_empty
Definition: token.hpp:61
lexy::token::encoding
typename Reader::encoding encoding
Definition: token.hpp:229
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:126
LEXY_PRECONDITION
#define LEXY_PRECONDITION(Expr)
Definition: assert.hpp:36
lexy::predefined_token_kind
predefined_token_kind
Definition: grammar.hpp:82
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::_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:209
lexy::token_kind::get
constexpr _underlying_type get() const noexcept
Definition: token.hpp:183
lexy::token::position
constexpr iterator position() const noexcept
Definition: token.hpp:252
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:242
lexy::whitespace_token_kind
@ whitespace_token_kind
Definition: grammar.hpp:87
lexy::token_kind
What sort of token it is.
Definition: token.hpp:99
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:189
lexy::token_kind::from_raw
static constexpr token_kind< TokenKind > from_raw(std::uint_least16_t kind) noexcept
Definition: token.hpp:203
LEXY_DECAY_DECLTYPE
#define LEXY_DECAY_DECLTYPE(...)
Definition: config.hpp:34
assert.hpp
lexy::error_token_kind
@ error_token_kind
Definition: grammar.hpp:86
lexy::token::_lexeme
lexy::lexeme< Reader > _lexeme
Definition: token.hpp:263
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:92
lexy::token_kind::token_kind_name
constexpr const friend char * token_kind_name(token_kind kind) noexcept
Definition: token.hpp:178
lexy::token_kind::token_kind
constexpr token_kind() noexcept
Creates an unknown token kind.
Definition: token.hpp:123
lexy::token::_kind
token_kind< TokenKind > _kind
Definition: token.hpp:264
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:171
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:193
lexy::token::char_type
typename encoding::char_type char_type
Definition: token.hpp:230
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:97
lexy::token_kind::_value
std::uint_least16_t _value
Definition: token.hpp:211
lexy::token::token
constexpr token(token_kind< TokenKind > kind, lexy::lexeme< Reader > lex) noexcept
Definition: token.hpp:233
lexy::token::name
constexpr const char * name() const noexcept
Definition: token.hpp:247
lexy::token_kind::to_raw
static constexpr std::uint_least16_t to_raw(token_kind< TokenKind > kind) noexcept
Definition: token.hpp:199
lexy::token_kind< void >::_underlying_type
lexy::_detail::type_or< void, int > _underlying_type
Definition: token.hpp:103
lexy::token_kind::is_predefined
constexpr bool is_predefined() const noexcept
Definition: token.hpp:160


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Dec 13 2024 03:19:17