1 /**
2 * Copyright (c) 2021-2024 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 <cctype>
23 #include <vector>
24
25 namespace ark::verifier::config {
26
27 using ark::parser::Action;
28 using ark::parser::Parser;
29 using ark::verifier::config::Section;
30
31 namespace {
32
33 struct Context {
34 Section current;
35 std::vector<Section> sections;
36 };
37
38 } // namespace
39
40 using P = ark::parser::Parser<Context, const char, const char *>;
41
ParseConfig(const char * str,Section & cfg)42 bool ParseConfig(const char *str, Section &cfg)
43 {
44 using ark::parser::Charset;
45 using P1 = P::P;
46 using P2 = P1::P;
47 using P3 = P2::P;
48 using P4 = P3::P;
49 using P5 = P4::P;
50 using P6 = P5::P;
51
52 static const auto CM = P::P::SkipComment("#");
53 static const auto WS = ~CM >> P::OfCharset(" \t\r\n");
54 static const auto NL = ~CM >> P1::OfCharset("\r\n");
55 static const auto SP = P2::OfCharset(" \t");
56 static const auto NAME_HANDLER = [](auto a, Context &c, auto from, auto to) {
57 if (a == Action::PARSED) {
58 c.current.name = PandaString {from, to};
59 }
60 return true;
61 };
62 static const auto NAME = P3::OfCharset("abcdefghijklmnopqrstuvwxyz_") |= NAME_HANDLER;
63
64 static const auto LCURL = P4::OfString("{");
65 static const auto RCURL = P5::OfString("}");
66
67 static const auto IS_COMMENT = [](auto s) {
68 for (char const c : s) {
69 if (c == '#') {
70 return true;
71 }
72 if (!isspace(c)) {
73 return false;
74 }
75 }
76 return false;
77 };
78
79 static const auto LINE_HANDLER = [](auto a, Context &c, auto from, auto to) {
80 if (a == Action::PARSED) {
81 auto item = PandaString {from, to};
82 if (!IS_COMMENT(item)) {
83 c.current.items.push_back(PandaString {from, to});
84 }
85 }
86 return true;
87 };
88
89 static const auto LINE = P6::OfCharset(!Charset {"\r\n"}) |= LINE_HANDLER;
90
91 static const auto SECTION_END = ~SP >> RCURL >> ~SP >> NL;
92 static const auto SECTION_START = ~SP >> NAME >> ~SP >> LCURL >> ~SP >> NL;
93 static const auto ITEM = (!SECTION_END) & (~SP >> LINE >> NL);
94
95 static const auto SECTION_HANDLER = [](auto a, Context &c) {
96 if (a == Action::START) {
97 c.sections.push_back(c.current);
98 c.current.sections.clear();
99 }
100 if (a == Action::CANCEL) {
101 c.current = c.sections.back();
102 c.sections.pop_back();
103 }
104 if (a == Action::PARSED) {
105 c.sections.back().sections.push_back(c.current);
106 c.current = c.sections.back();
107 c.sections.pop_back();
108 }
109 return true;
110 };
111
112 static P::P sectionRec;
113
114 static const auto SECTION = ~WS >> SECTION_START >> ~WS >> *sectionRec >> *ITEM >> SECTION_END >> ~WS |=
115 SECTION_HANDLER; // NOLINT
116
117 sectionRec = SECTION;
118
119 Context context;
120
121 context.current.name = "config";
122
123 if (SECTION(context, str, &str[std::strlen(str)])) { // NOLINT
124 cfg = context.current;
125 return true;
126 }
127
128 return false;
129 }
130
131 } // namespace ark::verifier::config
132