9
|
1 /*
|
|
2 ** Copyright (c) 2014-2017, Eren Okka
|
|
3 **
|
|
4 ** This Source Code Form is subject to the terms of the Mozilla Public
|
|
5 ** License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
6 ** file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
7 */
|
|
8
|
|
9 #include <algorithm>
|
|
10
|
|
11 #include "token.h"
|
|
12
|
|
13 namespace anitomy {
|
|
14
|
|
15 Token::Token() : category(kUnknown), enclosed(false) {
|
|
16 }
|
|
17
|
|
18 Token::Token(TokenCategory category, const string_t& content, bool enclosed)
|
|
19 : category(category), content(content), enclosed(enclosed) {
|
|
20 }
|
|
21
|
|
22 bool Token::operator==(const Token& token) const {
|
|
23 return category == token.category && content == token.content && enclosed == token.enclosed;
|
|
24 }
|
|
25
|
|
26 ////////////////////////////////////////////////////////////////////////////////
|
|
27
|
|
28 static bool CheckTokenFlags(const Token& token, unsigned int flags) {
|
|
29 auto check_flag = [&flags](unsigned int flag) { return (flags & flag) == flag; };
|
|
30
|
|
31 if (flags & kFlagMaskEnclosed) {
|
|
32 bool success = check_flag(kFlagEnclosed) ? token.enclosed : !token.enclosed;
|
|
33 if (!success)
|
|
34 return false;
|
|
35 }
|
|
36
|
|
37 if (flags & kFlagMaskCategories) {
|
|
38 bool success = false;
|
|
39 auto check_category = [&](TokenFlag fe, TokenFlag fn, TokenCategory c) {
|
|
40 if (!success)
|
|
41 success = check_flag(fe) ? token.category == c : check_flag(fn) ? token.category != c : false;
|
|
42 };
|
|
43 check_category(kFlagBracket, kFlagNotBracket, kBracket);
|
|
44 check_category(kFlagDelimiter, kFlagNotDelimiter, kDelimiter);
|
|
45 check_category(kFlagIdentifier, kFlagNotIdentifier, kIdentifier);
|
|
46 check_category(kFlagUnknown, kFlagNotUnknown, kUnknown);
|
|
47 check_category(kFlagNotValid, kFlagValid, kInvalid);
|
|
48 if (!success)
|
|
49 return false;
|
|
50 }
|
|
51
|
|
52 return true;
|
|
53 }
|
|
54
|
|
55 template <class iterator_t> static iterator_t FindTokenBase(iterator_t first, iterator_t last, unsigned int flags) {
|
|
56 return std::find_if(first, last, [&](const Token& token) { return CheckTokenFlags(token, flags); });
|
|
57 }
|
|
58
|
|
59 token_iterator_t FindToken(token_iterator_t first, token_iterator_t last, unsigned int flags) {
|
|
60 return FindTokenBase(first, last, flags);
|
|
61 }
|
|
62
|
|
63 token_reverse_iterator_t FindToken(token_reverse_iterator_t first, token_reverse_iterator_t last, unsigned int flags) {
|
|
64 return FindTokenBase(first, last, flags);
|
|
65 }
|
|
66
|
|
67 token_iterator_t FindPreviousToken(token_container_t& tokens, token_iterator_t first, unsigned int flags) {
|
|
68 auto it = FindToken(std::reverse_iterator<token_iterator_t>(first), tokens.rend(), flags);
|
|
69 return it == tokens.rend() ? tokens.end() : (++it).base();
|
|
70 }
|
|
71
|
|
72 token_iterator_t FindNextToken(token_container_t& tokens, token_iterator_t first, unsigned int flags) {
|
|
73 return FindToken(++first, tokens.end(), flags);
|
|
74 }
|
|
75
|
|
76 } // namespace anitomy
|