1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef PANDA_VERIFIER_DEBUG_MSG_SET_PARSER_H_
17 #define PANDA_VERIFIER_DEBUG_MSG_SET_PARSER_H_
18
19 #include "runtime/include/mem/panda_containers.h"
20 #include "verification/util/parser/parser.h"
21 #include "verifier_messages.h"
22
23 namespace panda::verifier::debug {
24
25 struct MessageSetContext {
26 panda::PandaVector<std::pair<size_t, size_t>> stack;
27 panda::PandaUnorderedSet<size_t> nums;
28 };
29
30 namespace {
31 using panda::parser::action;
32
33 static const auto NAME_HANDLER = [](action a, MessageSetContext &c, auto from, auto to) {
34 if (a == action::PARSED) {
35 std::string_view name {from, static_cast<size_t>(to - from)};
36 size_t num = static_cast<size_t>(panda::verifier::StringToVerifierMessage(name));
37 c.stack.push_back(std::make_pair(num, num));
38 }
39 return true;
40 };
41
42 static const auto NUM_HANDLER = [](action a, MessageSetContext &c, auto from) {
43 if (a == action::PARSED) {
44 size_t num = std::strtol(from, nullptr, 0);
45 c.stack.push_back(std::make_pair(num, num));
46 }
47 return true;
48 };
49
50 static const auto RANGE_HANDLER = [](action a, MessageSetContext &c) {
51 if (a == action::PARSED) {
52 auto num_end = c.stack.back();
53 c.stack.pop_back();
54 auto num_start = c.stack.back();
55 c.stack.pop_back();
56
57 c.stack.push_back(std::make_pair(num_start.first, num_end.first));
58 }
59 return true;
60 };
61
62 static const auto ITEM_HANDLER = [](action a, MessageSetContext &c) {
63 if (a == action::START) {
64 c.stack.clear();
65 }
66 if (a == action::PARSED) {
67 auto range = c.stack.back();
68 c.stack.pop_back();
69
70 for (auto i = range.first; i <= range.second; ++i) {
71 c.nums.insert(i);
72 }
73 }
74 return true;
75 };
76 } // namespace
77
MessageSetParser()78 const auto &MessageSetParser()
79 {
80 using panda::parser::action;
81 using panda::parser::charset;
82 using panda::parser::parser;
83
84 using p = parser<MessageSetContext, const char, const char *>;
85 using p1 = typename p::p;
86 using p2 = typename p1::p;
87 using p3 = typename p2::p;
88 using p4 = typename p3::p;
89
90 static const auto WS = p::of_charset(" \t\r\n");
91 static const auto COMMA = p1::of_charset(",");
92 static const auto DEC = p2::of_charset("0123456789");
93
94 static const auto NAME = p3::of_charset("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789") |=
95 NAME_HANDLER;
96
97 static const auto NUM = DEC |= NUM_HANDLER;
98
99 static const auto MSG = NUM | NAME;
100
101 static const auto MSG_RANGE = MSG >> ~WS >> p4::of_string("-") >> ~WS >> MSG |= RANGE_HANDLER;
102
103 static const auto ITEM = ~WS >> ((MSG_RANGE | MSG) |= ITEM_HANDLER) >> ~WS >> ~COMMA;
104
105 // clang-tidy bug, use lambda instead of ITEMS = *ITEM
106 static const auto ITEMS = [](MessageSetContext &c, const char *&start, const char *end) {
107 while (true) {
108 auto saved = start;
109 if (!ITEM(c, start, end)) {
110 start = saved;
111 break;
112 }
113 }
114 return true;
115 };
116
117 return ITEMS;
118 }
119
120 } // namespace panda::verifier::debug
121
122 #endif //! PANDA_VERIFIER_DEBUG_MSG_SET_PARSER_H_
123