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