Line data Source code
1 : // Author(s): Wieger Wesselink
2 : // Copyright: see the accompanying file COPYING or copy at
3 : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4 : //
5 : // Distributed under the Boost Software License, Version 1.0.
6 : // (See accompanying file LICENSE_1_0.txt or copy at
7 : // http://www.boost.org/LICENSE_1_0.txt)
8 : //
9 : /// \file mcrl2/process/detail/alphabet_parse.h
10 : /// \brief add your file description here.
11 :
12 : #ifndef MCRL2_PROCESS_DETAIL_ALPHABET_PARSE_H
13 : #define MCRL2_PROCESS_DETAIL_ALPHABET_PARSE_H
14 :
15 : #include "mcrl2/process/multi_action_name.h"
16 : #include "mcrl2/process/parse.h"
17 :
18 : namespace mcrl2 {
19 :
20 : namespace process {
21 :
22 : namespace detail {
23 :
24 : // Removes surrounding braces from a string.
25 : inline
26 51 : std::string remove_braces(const std::string& text)
27 : {
28 51 : std::string s = utilities::trim_copy(text);
29 51 : if (s.size() < 2 || s.front() != '{' || s.back() != '}')
30 : {
31 0 : throw mcrl2::runtime_error("Expected braces around string: " + text);
32 : }
33 51 : s = s.substr(1, s.size() - 2);
34 102 : return utilities::trim_copy(s);
35 51 : }
36 :
37 : // Removes a trailing @ symbol from a string, if it exists.
38 : // Returns the resulting string, and a boolean indicating if an @ symbol was removed.
39 : inline
40 34 : std::pair<std::string, bool> remove_trailing_at_symbol(const std::string& text)
41 : {
42 34 : std::string s = utilities::trim_copy(text);
43 34 : bool found_at_symbol = false;
44 34 : if (!s.empty() && s.back() == '@')
45 : {
46 6 : found_at_symbol = true;
47 6 : s.erase(s.size() - 1);
48 : }
49 68 : return { s, found_at_symbol };
50 34 : }
51 :
52 : // Returns the elements of a comma separated list inside braces.
53 : // For example "{ s1, s2, s3 }" -> [s1, s2, s3]
54 : inline
55 51 : std::vector<std::string> set_elements(const std::string& text)
56 : {
57 51 : std::string s = remove_braces(text);
58 102 : return utilities::regex_split(s, "\\s*,\\s*");
59 51 : }
60 :
61 : // Returns the left and right hand sides of strings separated by "->".
62 : // For example "s1 -> s2" -> [s1, s2]
63 : inline
64 15 : std::pair<std::string, std::string> split_arrow(const std::string& text)
65 : {
66 15 : std::string s = utilities::trim_copy(text);
67 30 : std::vector<std::string> w = utilities::regex_split(s, "\\s*->\\s*");
68 15 : if (w.size() != 2)
69 : {
70 0 : throw mcrl2::runtime_error("Expected a string of the shape lhs -> rhs: " + text);
71 : }
72 30 : return { w[0], w[1] };
73 15 : }
74 :
75 : // Returns the elements of a bar separated list.
76 : // For example "s1 | s2 | s3" -> [s1, s2, s3]
77 : inline
78 10 : std::vector<std::string> split_bar(const std::string& text)
79 : {
80 10 : std::string s = utilities::trim_copy(text);
81 20 : return utilities::regex_split(s, R"(\s*\|\s*)");
82 10 : }
83 :
84 : // Splits a word into characters.
85 : inline
86 60 : std::vector<std::string> split_characters(const std::string& text)
87 : {
88 60 : std::string s = utilities::trim_copy(text);
89 60 : std::vector<std::string> result;
90 182 : for (char & i : s)
91 : {
92 122 : result.emplace_back(1, i);
93 : }
94 120 : return result;
95 60 : }
96 :
97 : // Converts a vector of strings into an identifier_string_list.
98 : inline
99 13 : core::identifier_string_list make_identifier_string_list(const std::vector<std::string>& words)
100 : {
101 13 : std::vector<core::identifier_string> ids;
102 33 : for (const std::string& word: words)
103 : {
104 20 : ids.emplace_back(word);
105 : }
106 26 : return core::identifier_string_list(ids.begin(), ids.end());
107 13 : }
108 :
109 : // Converts a list of strings into a multi action name.
110 : inline
111 60 : multi_action_name make_multi_action(const std::vector<std::string>& words)
112 : {
113 60 : multi_action_name result;
114 182 : for (const std::string& word: words)
115 : {
116 122 : result.insert(core::identifier_string(word));
117 : }
118 60 : return result;
119 0 : }
120 :
121 : // Parses a multi action name.
122 : // Example: "s1 | s2 | s3" -> {s1, s2, s3}.
123 : inline
124 0 : multi_action_name parse_multi_action_name(const std::string& text)
125 : {
126 0 : return make_multi_action(split_bar(text));
127 : }
128 :
129 : // Parses a multi action name set.
130 : // Example: "{ s1 | s2 | s3, t1 | t2 }" -> {{s1, s2, s3}, {t2, t2}}
131 0 : multi_action_name_set parse_multi_action_name_set(const std::string& text)
132 : {
133 0 : std::vector<multi_action_name> result;
134 0 : for (const std::string& word: set_elements(text))
135 : {
136 0 : result.push_back(parse_multi_action_name(word));
137 0 : }
138 0 : return multi_action_name_set(result.begin(), result.end());
139 0 : }
140 :
141 : // Parses a multi action name. It is assumed that the actions consist of one character.
142 : // Example: "abc" -> {a, b, c}.
143 : inline
144 60 : multi_action_name parse_simple_multi_action_name(const std::string& text)
145 : {
146 120 : return make_multi_action(split_characters(text));
147 : }
148 :
149 : // Parses a multi action name set, optionally followed by an @ symbol.
150 : // It is assumed that the actions consist of one character.
151 : // Example: "{ abc, de }@" -> [{{a, b, c}, {d, e}}, true].
152 : inline
153 34 : std::pair<multi_action_name_set, bool> parse_simple_multi_action_name_set(const std::string& text)
154 : {
155 34 : multi_action_name_set result;
156 34 : auto p = remove_trailing_at_symbol(text);
157 34 : std::string s = p.first;
158 34 : bool result_includes_subsets = p.second;
159 :
160 92 : for (const std::string& word: set_elements(s))
161 : {
162 58 : result.insert(parse_simple_multi_action_name(word));
163 34 : }
164 68 : return { result, result_includes_subsets };
165 34 : }
166 :
167 : inline
168 2 : action_name_multiset_list parse_allow_set(const std::string& text)
169 : {
170 2 : std::vector<action_name_multiset> result;
171 8 : for (const std::string& word: set_elements(text))
172 : {
173 6 : result.emplace_back(make_identifier_string_list(split_bar(word)));
174 2 : }
175 4 : return action_name_multiset_list(result.begin(), result.end());
176 2 : }
177 :
178 : inline
179 3 : core::identifier_string_list parse_block_set(const std::string& text)
180 : {
181 6 : return make_identifier_string_list(set_elements(text));
182 : }
183 :
184 : inline
185 4 : communication_expression_list parse_comm_set(const std::string& text)
186 : {
187 4 : std::vector<communication_expression> result;
188 8 : for (const std::string& word: set_elements(text))
189 : {
190 4 : auto [lhs, rhs] = split_arrow(word);
191 4 : result.emplace_back(mcrl2::process::action_name_multiset(make_identifier_string_list(split_bar(lhs))), core::identifier_string(rhs));
192 8 : }
193 8 : return communication_expression_list(result.begin(), result.end());
194 4 : }
195 :
196 : inline
197 8 : rename_expression_list parse_rename_set(const std::string& text)
198 : {
199 8 : std::vector<rename_expression> result;
200 19 : for (const std::string& word: set_elements(text))
201 : {
202 11 : auto [lhs, rhs] = split_arrow(word);
203 11 : result.emplace_back(core::identifier_string(lhs), core::identifier_string(rhs));
204 19 : }
205 16 : return rename_expression_list(result.begin(), result.end());
206 8 : }
207 :
208 : } // namespace detail
209 :
210 : } // namespace process
211 :
212 : } // namespace mcrl2
213 :
214 : #endif // MCRL2_PROCESS_DETAIL_ALPHABET_PARSE_H
|