1 /*
2 * Copyright (c) 2021 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 #include "config_parse.h"
17 #include "verification/debug/parser/parser.h"
18 #include "runtime/include/mem/panda_string.h"
19
20 #include <vector>
21
22 namespace panda::verifier::config {
23
24 using panda::parser::action;
25 using panda::parser::parser;
26 using panda::verifier::config::Section;
27
28 namespace {
29
30 struct Context {
31 Section current;
32 std::vector<Section> sections;
33 };
34
35 } // namespace
36
37 using p = panda::parser::parser<Context, const char, const char *>;
38
39 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE)
ParseConfig(const char * str,Section & cfg)40 bool ParseConfig(const char *str, Section &cfg)
41 {
42 using panda::parser::charset;
43 using p1 = p::p;
44 using p2 = p1::p;
45 using p3 = p2::p;
46 using p4 = p3::p;
47 using p5 = p4::p;
48 using p6 = p5::p;
49
50 static const auto WS = p::of_charset(" \t\r\n");
51 static const auto NL = p1::of_charset("\r\n");
52 static const auto SP = p2::of_charset(" \t");
53 static const auto NAME_HANDLER = [](auto a, Context &c, auto from, auto to) {
54 if (a == action::PARSED) {
55 c.current.name = PandaString {from, to};
56 }
57 return true;
58 };
59 static const auto NAME = p3::of_charset("abcdefghijklmnopqrstuvwxyz_") |= NAME_HANDLER;
60
61 static const auto LCURL = p4::of_string("{");
62 static const auto RCURL = p5::of_string("}");
63
64 static const auto LINE_HANDLER = [](auto a, Context &c, auto from, auto to) {
65 if (a == action::PARSED) {
66 c.current.items.push_back(PandaString {from, to});
67 }
68 return true;
69 };
70
71 static const auto LINE = p6::of_charset(!charset {"\r\n"}) |= LINE_HANDLER;
72
73 static const auto SECTION_END = ~SP >> RCURL >> ~SP >> NL;
74 static const auto SECTION_START = ~SP >> NAME >> ~SP >> LCURL >> ~SP >> NL;
75 static const auto ITEM = (!SECTION_END) & (~SP >> LINE >> NL);
76
77 static const auto SECTION_HANDLER = [](auto a, Context &c) {
78 if (a == action::START) {
79 c.sections.push_back(c.current);
80 c.current.sections.clear();
81 }
82 if (a == action::CANCEL) {
83 c.current = c.sections.back();
84 c.sections.pop_back();
85 }
86 if (a == action::PARSED) {
87 c.sections.back().sections.push_back(c.current);
88 c.current = c.sections.back();
89 c.sections.pop_back();
90 }
91 return true;
92 };
93
94 static p::p section_rec;
95
96 static const auto SECTION = ~WS >> SECTION_START >> ~WS >> *section_rec >> *ITEM >> SECTION_END >> ~WS |=
97 SECTION_HANDLER; // NOLINT
98
99 section_rec = SECTION;
100
101 Context context;
102
103 context.current.name = "config";
104
105 if (SECTION(context, str, &str[std::strlen(str)])) { // NOLINT
106 cfg = context.current;
107 return true;
108 }
109
110 return false;
111 }
112
113 } // namespace panda::verifier::config
114