10
10
#include < string>
11
11
#include < type_traits>
12
12
13
- template <class InputIterator >
13
+ template <class I >
14
+ concept CharIterator = std::same_as<typename std::iterator_traits<I>::value_type, char >;
15
+
16
+ template <CharIterator InputIterator>
14
17
class Lexer {
15
18
16
19
public:
@@ -21,9 +24,6 @@ class Lexer {
21
24
using reference = Token &;
22
25
23
26
private:
24
- static_assert (std::is_same<typename std::iterator_traits<InputIterator>::value_type, char >(),
25
- " Expecting iterator over 'char' type." );
26
-
27
27
InputIterator current_character;
28
28
InputIterator characters_end;
29
29
@@ -42,13 +42,14 @@ class Lexer {
42
42
private:
43
43
std::optional<Token> next ();
44
44
template <class TokenMatcher >
45
+ requires std::is_invocable_r_v<bool , TokenMatcher, char >
45
46
std::string get_while_matching (const TokenMatcher &matcher);
46
47
47
48
static bool is_operator (char c);
48
49
static bool is_identifier (char c);
49
50
};
50
51
51
- template <class InputIterator >
52
+ template <CharIterator InputIterator>
52
53
Lexer<InputIterator>::Lexer(InputIterator begin, InputIterator end)
53
54
: current_character(begin)
54
55
, characters_end(end) {
@@ -57,34 +58,34 @@ Lexer<InputIterator>::Lexer(InputIterator begin, InputIterator end)
57
58
}
58
59
}
59
60
60
- template <class InputIterator >
61
+ template <CharIterator InputIterator>
61
62
Token Lexer<InputIterator>::operator *() const {
62
63
return *current_token;
63
64
}
64
65
65
- template <class InputIterator >
66
+ template <CharIterator InputIterator>
66
67
Token &Lexer<InputIterator>::operator ++() {
67
68
return *(current_token = next ());
68
69
}
69
70
70
- template <class InputIterator >
71
+ template <CharIterator InputIterator>
71
72
Token Lexer<InputIterator>::operator ++(int ) {
72
73
auto tmp_token = std::move (current_token);
73
74
++(*this );
74
75
return *tmp_token;
75
76
}
76
77
77
- template <class InputIterator >
78
+ template <CharIterator InputIterator>
78
79
bool Lexer<InputIterator>::operator ==(const Lexer &other) const {
79
80
return current_token.has_value () == other.current_token .has_value ();
80
81
}
81
82
82
- template <class InputIterator >
83
+ template <CharIterator InputIterator>
83
84
bool Lexer<InputIterator>::operator !=(const Lexer &other) const {
84
85
return !(*this == other);
85
86
}
86
87
87
- template <class InputIterator >
88
+ template <CharIterator InputIterator>
88
89
std::optional<Token> Lexer<InputIterator>::next() {
89
90
while (current_character != characters_end) {
90
91
if (isspace (*current_character) != 0 ) {
@@ -123,8 +124,9 @@ std::optional<Token> Lexer<InputIterator>::next() {
123
124
return {};
124
125
}
125
126
126
- template <class InputIterator >
127
+ template <CharIterator InputIterator>
127
128
template <class TokenMatcher >
129
+ requires std::is_invocable_r_v<bool , TokenMatcher, char >
128
130
std::string Lexer<InputIterator>::get_while_matching(const TokenMatcher &matcher) {
129
131
std::string value;
130
132
do {
@@ -133,12 +135,12 @@ std::string Lexer<InputIterator>::get_while_matching(const TokenMatcher &matcher
133
135
return value;
134
136
}
135
137
136
- template <class InputIterator >
138
+ template <CharIterator InputIterator>
137
139
bool Lexer<InputIterator>::is_operator(const char c) {
138
140
return c == ' +' || c == ' -' || c == ' *' || c == ' /' || c == ' %' ;
139
141
}
140
142
141
- template <class InputIterator >
143
+ template <CharIterator InputIterator>
142
144
bool Lexer<InputIterator>::is_identifier(const char c) {
143
145
return (isalnum (c) != 0 ) || c == ' _' ;
144
146
}
0 commit comments