Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
PnmlParser.cpp
Go to the documentation of this file.
1
3#ifdef STORM_HAVE_XERCES
4#include <iostream>
5
7
11
12namespace {
13bool isOnlyWhitespace(std::string const& in) {
14 return std::all_of(in.begin(), in.end(), [](char c) { return std::isspace(static_cast<unsigned char>(c)); });
15}
16} // namespace
17namespace storm {
18namespace parser {
19
20storm::gspn::GSPN* PnmlParser::parse(xercesc::DOMElement const* elementRoot) {
21 if (storm::adapters::getName(elementRoot) == "pnml") {
22 traversePnmlElement(elementRoot);
23 } else {
24 // If the top-level node is not a "pnml" or "" node, then throw an exception.
25 STORM_LOG_THROW(false, storm::exceptions::UnexpectedException, "Failed to identify the root element.");
26 }
27 return builder.buildGspn();
28}
29
30void PnmlParser::traversePnmlElement(xercesc::DOMElement const* const element) {
31 // traverse attributes
32 for (uint_fast64_t i = 0; i < element->getAttributes()->getLength(); ++i) {
33 auto attr = element->getAttributes()->item(i);
34 auto name = storm::adapters::getName(attr);
35
36 // Found node or attribute which is at the moment nod handled by this parser.
37 // Notify the user and continue the parsing.
38 STORM_LOG_WARN("unknown attribute (node=pnml): " + name + "\n");
39 }
40
41 // traverse children
42 for (uint_fast64_t i = 0; i < element->getChildNodes()->getLength(); ++i) {
43 auto child = element->getChildNodes()->item(i);
44 auto name = storm::adapters::getName(child);
45
46 if (name == "net") {
47 traverseNetOrPage(child);
48 } else if (isOnlyWhitespace(name)) {
49 // ignore node (contains only whitespace)
50 } else {
51 // Found node or attribute which is at the moment nod handled by this parser.
52 // Notify the user and continue the parsing.
53 STORM_LOG_WARN("unknown child (node=pnml): " + name + "\n");
54 }
55 }
56}
57
58void PnmlParser::traverseNetOrPage(xercesc::DOMNode const* const node) {
59 // traverse attributes
60 for (uint_fast64_t i = 0; i < node->getAttributes()->getLength(); ++i) {
61 auto attr = node->getAttributes()->item(i);
62 auto name = storm::adapters::getName(attr);
63
64 if (name == "id") {
65 builder.setGspnName(storm::adapters::XMLtoString(attr->getNodeValue()));
66 } else {
67 // Found node or attribute which is at the moment nod handled by this parser.
68 // Notify the user and continue the parsing.
69 STORM_LOG_WARN("unknown attribute (node=" + storm::adapters::XMLtoString(node->getNodeName()) + "): " + name + "\n");
70 }
71 }
72
73 // traverse children
74 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
75 auto child = node->getChildNodes()->item(i);
76 auto name = storm::adapters::getName(child);
77
78 if (name == "place") {
79 traversePlace(child);
80 } else if (name == "transition") {
81 traverseTransition(child);
82 } else if (name == "arc") {
83 traverseArc(child);
84 } else if (name == "page") {
85 // Some pnml files have a child named page.
86 // The page node has the same children like the net node (e.g., place, transition, arc)
87 traverseNetOrPage(child);
88 } else if (isOnlyWhitespace(name)) {
89 // ignore node (contains only whitespace)
90 } else {
91 // Found node or attribute which is at the moment nod handled by this parser.
92 // Notify the user and continue the parsing.
93 STORM_LOG_WARN("unknown child (node=" + storm::adapters::XMLtoString(node->getNodeName()) + "): " + name + "\n");
94 }
95 }
96}
97
98void PnmlParser::traversePlace(xercesc::DOMNode const* const node) {
99 std::string placeName;
100 // the first entry is false if the corresponding information was not found in the pnml file
101 std::pair<bool, uint_fast64_t> numberOfInitialTokens(false, defaultNumberOfInitialTokens);
102 std::pair<bool, boost::optional<uint64_t>> capacity(false, boost::none);
103
104 // traverse attributes
105 for (uint_fast64_t i = 0; i < node->getAttributes()->getLength(); ++i) {
106 auto attr = node->getAttributes()->item(i);
107 auto name = storm::adapters::getName(attr);
108
109 if (name == "id") {
110 placeName = storm::adapters::XMLtoString(attr->getNodeValue());
111 } else {
112 // Found node or attribute which is at the moment nod handled by this parser.
113 // Notify the user and continue the parsing.
114 STORM_LOG_WARN("unknown attribute (node=place): " + name + "\n");
115 }
116 }
117
118 // traverse children
119 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
120 auto child = node->getChildNodes()->item(i);
121 auto name = storm::adapters::getName(child);
122
123 if (name == "initialMarking") {
124 numberOfInitialTokens.first = true;
125 numberOfInitialTokens.second = traverseInitialMarking(child);
126 } else if (name == "capacity") {
127 capacity.first = true;
128 capacity.second = traverseCapacity(child);
129 } else if (isOnlyWhitespace(name)) {
130 // ignore node (contains only whitespace)
131 } else if (name == "name" || name == "graphics") {
132 // ignore these tags
133 } else {
134 // Found node or attribute which is at the moment nod handled by this parser.
135 // Notify the user and continue the parsing.
136 STORM_LOG_WARN("unknown child (node=place): " + name + "\n");
137 }
138 }
139
140 if (!numberOfInitialTokens.first) {
141 // no information about the number of initial tokens is found
142 // use the default number of initial tokens
143 STORM_LOG_WARN("unknown numberOfInitialTokens (place=" + placeName + ")\n");
144 }
145 if (!capacity.first) {
146 // no information about the capacity is found
147 STORM_LOG_WARN("unknown capacity (place=" + placeName + ")\n");
148 }
149 builder.addPlace(capacity.second, numberOfInitialTokens.first ? numberOfInitialTokens.second : 0, placeName);
150}
151
152void PnmlParser::traverseTransition(xercesc::DOMNode const* const node) {
153 // the first entry is false if the corresponding information was not found in the pnml file
154 std::pair<bool, bool> timed(false, defaultTransitionType);
155 std::pair<bool, std::string> value(false, "");
156 std::string id;
157 uint_fast64_t priority = defaultPriority;
158
159 // parse attributes
160 for (uint_fast64_t i = 0; i < node->getAttributes()->getLength(); ++i) {
161 auto attr = node->getAttributes()->item(i);
162 auto name = storm::adapters::getName(attr);
163
164 if (name == "id") {
165 id = storm::adapters::XMLtoString(attr->getNodeValue());
166 } else {
167 // Found node or attribute which is at the moment nod handled by this parser.
168 // Notify the user and continue the parsing.
169 STORM_LOG_WARN("unknown attribute (node=transition): " + name + "\n");
170 }
171 }
172
173 // traverse children
174 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
175 auto child = node->getChildNodes()->item(i);
176 auto name = storm::adapters::getName(child);
177
178 if (name == "rate") {
179 value.first = true;
180 value.second = traverseTransitionValue(child);
181 } else if (name == "timed") {
182 timed.first = true;
183 timed.second = traverseTransitionType(child);
184 } else if (name == "priority") {
185 priority = traversePriority(child);
186 } else if (isOnlyWhitespace(name)) {
187 // ignore node (contains only whitespace)
188 } else if (name == "graphics" || name == "name" || name == "orientation") {
189 // ignore these tags
190 } else {
191 // Found node or attribute which is at the moment nod handled by this parser.
192 // Notify the user and continue the parsing.
193 STORM_LOG_WARN("unknown child (node=transition): " + name + "\n");
194 }
195 }
196
197 // build transition and add it to the GSPN
198 STORM_LOG_THROW(timed.first, storm::exceptions::UnexpectedException, "Unknown transition type (transition=" + id + ").");
199
200 if (timed.second) {
201 // no information about the rate is found -> abort the parsing
202 STORM_LOG_THROW(value.first, storm::exceptions::UnexpectedException, "Unknown transition rate (transition=" + id + ").");
203 builder.addTimedTransition(priority, std::stod(value.second), id);
204 } else {
205 if (!value.first) {
206 // no information about the weight is found
207 // continue with the default weight
208 STORM_LOG_WARN("unknown transition weight (transition=" + id + ")\n");
209 }
210 builder.addImmediateTransition(priority, std::stod(value.second), id);
211 }
212}
213
214void PnmlParser::traverseArc(xercesc::DOMNode const* const node) {
215 // the first entry is false if the corresponding information was not found in the pnml file
216 std::pair<bool, std::string> source(false, "");
217 std::pair<bool, std::string> target(false, "");
218 std::pair<bool, std::string> type(false, defaultArcType);
219 std::pair<bool, uint_fast64_t> multiplicity(false, defaultMultiplicity);
220 std::string id;
221
222 // parse attributes
223 for (uint_fast64_t i = 0; i < node->getAttributes()->getLength(); ++i) {
224 auto attr = node->getAttributes()->item(i);
225 auto name = storm::adapters::getName(attr);
226
227 if (name == "source") {
228 source.first = true;
229 source.second = storm::adapters::XMLtoString(attr->getNodeValue());
230 } else if (name == "target") {
231 target.first = true;
232 target.second = storm::adapters::XMLtoString(attr->getNodeValue());
233 } else if (name == "id") {
234 id = storm::adapters::XMLtoString(attr->getNodeValue());
235 } else {
236 // Found node or attribute which is at the moment nod handled by this parser.
237 // Notify the user and continue the parsing.
238 STORM_LOG_WARN("unknown attribute (node=arc): " + name + "\n");
239 }
240 }
241
242 // parse children
243 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
244 auto child = node->getChildNodes()->item(i);
245 auto name = storm::adapters::getName(child);
246 if (name == "type") {
247 type.first = true;
248 type.second = traverseArcType(child);
249 } else if (name == "inscription") {
250 multiplicity.first = true;
251 multiplicity.second = traverseMultiplicity(child);
252 } else if (isOnlyWhitespace(name)) {
253 // ignore node (contains only whitespace)
254 } else if (name == "graphics" || name == "arcpath" || name == "tagged") {
255 // ignore these tags
256 } else {
257 // Found node or attribute which is at the moment nod handled by this parser.
258 // Notify the user and continue the parsing.
259 STORM_LOG_WARN("unknown child (node=arc): " + name + "\n");
260 }
261 }
262
263 // check if all necessary information where stored in the pnml file
264 // could not find start of the arc -> abort parsing
265 STORM_LOG_THROW(source.first, storm::exceptions::UnexpectedException, "Unknown arc source (arc=" + id + ").");
266 // could not find the target of the arc -> abort parsing
267 STORM_LOG_THROW(target.first, storm::exceptions::UnexpectedException, "Unknown arc target (arc=" + id + ").");
268 if (!multiplicity.first) {
269 // no information about the multiplicity of the arc
270 // continue and use the default multiplicity
271 STORM_LOG_WARN("unknown multiplicity (node=arc): " + id + "\n");
272 }
273
274 if (type.second == "normal") {
275 builder.addNormalArc(source.second, target.second, multiplicity.second);
276 } else if (type.second == "inhibition") {
277 builder.addInhibitionArc(source.second, target.second, multiplicity.second);
278 } else {
279 STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Arc type '" << type.second << "' in arc '" << id << "' is unknown.");
280 }
281}
282
283uint_fast64_t PnmlParser::traverseInitialMarking(xercesc::DOMNode const* const node) {
284 uint_fast64_t result = defaultNumberOfInitialTokens;
285 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
286 auto child = node->getChildNodes()->item(i);
287 auto name = storm::adapters::getName(child);
288 if (name == "text") {
289 result = std::stoull(storm::adapters::getName(child->getFirstChild()));
290 } else if (name == "value") {
291 auto value = storm::adapters::getName(child->getFirstChild());
292 value = value.substr(std::string("Default,").length());
293 result = std::stoull(value);
294 } else if (isOnlyWhitespace(name)) {
295 // ignore node (contains only whitespace)
296 } else if (name == "graphics") {
297 // ignore these tags
298 } else {
299 // Found node or attribute which is at the moment nod handled by this parser.
300 // Notify the user and continue the parsing.
301 STORM_LOG_WARN("unknown child (node=initialMarking): " + name + "\n");
302 }
303 }
304 return result;
305}
306
307int_fast64_t PnmlParser::traverseCapacity(xercesc::DOMNode const* const node) {
308 int_fast64_t result = defaultCapacity;
309 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
310 auto child = node->getChildNodes()->item(i);
311 auto name = storm::adapters::getName(child);
312 if (name == "value") {
313 auto value = storm::adapters::getName(child->getFirstChild());
314 if (value.find("Default,") == 0) {
315 value = value.substr(std::string("Default,").length());
316 }
317 result = std::stoull(value);
318 } else if (name == "graphics") {
319 // ignore these nodes
320 } else if (isOnlyWhitespace(name)) {
321 // ignore node (contains only whitespace)
322 } else {
323 // Found node or attribute which is at the moment nod handled by this parser.
324 // Notify the user and continue the parsing.
325 STORM_LOG_WARN("unknown child (node=capacity): " + name + "\n");
326 }
327 }
328 return result;
329}
330
331uint_fast64_t PnmlParser::traverseMultiplicity(xercesc::DOMNode const* const node) {
332 uint_fast64_t result = defaultMultiplicity;
333 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
334 auto child = node->getChildNodes()->item(i);
335 auto name = storm::adapters::getName(child);
336 if (name == "value") {
337 auto value = storm::adapters::getName(child->getFirstChild());
338 if (value.find("Default,") == 0) {
339 value = value.substr(std::string("Default,").length());
340 }
341 result = std::stoull(value);
342 } else if (name == "graphics") {
343 // ignore these nodes
344 } else if (isOnlyWhitespace(name)) {
345 // ignore node (contains only whitespace)
346 } else {
347 // Found node or attribute which is at the moment nod handled by this parser.
348 // Notify the user and continue the parsing.
349 STORM_LOG_WARN("unknown child (node=inscription): " + name + "\n");
350 }
351 }
352 return result;
353}
354
355std::string PnmlParser::traverseTransitionValue(xercesc::DOMNode const* const node) {
356 std::string result;
357 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
358 auto child = node->getChildNodes()->item(i);
359 auto name = storm::adapters::getName(child);
360 if (name == "value") {
361 result = storm::adapters::getName(child->getFirstChild());
362 } else if (isOnlyWhitespace(name)) {
363 // ignore node (contains only whitespace)
364 } else {
365 // Found node or attribute which is at the moment nod handled by this parser.
366 // Notify the user and continue the parsing.
367 STORM_LOG_WARN("unknown child (node=rate): " + name + "\n");
368 }
369 }
370 return result;
371}
372
373bool PnmlParser::traverseTransitionType(xercesc::DOMNode const* const node) {
374 bool result;
375 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
376 auto child = node->getChildNodes()->item(i);
377 auto name = storm::adapters::getName(child);
378 if (name == "value") {
379 result = storm::adapters::getName(child->getFirstChild()) == "true";
380 } else if (isOnlyWhitespace(name)) {
381 // ignore node (contains only whitespace)
382 } else {
383 // Found node or attribute which is at the moment nod handled by this parser.
384 // Notify the user and continue the parsing.
385 STORM_LOG_WARN("unknown child (node=timed): " + name + "\n");
386 }
387 }
388 return result;
389}
390
391std::string PnmlParser::traverseArcType(xercesc::DOMNode const* const node) {
392 for (uint_fast64_t i = 0; i < node->getAttributes()->getLength(); ++i) {
393 auto attr = node->getAttributes()->item(i);
394 auto name = storm::adapters::getName(attr);
395 if (name == "value") {
396 return storm::adapters::XMLtoString(attr->getNodeValue());
397 } else {
398 // Found node or attribute which is at the moment nod handled by this parser.
399 // Notify the user and continue the parsing.
400 STORM_LOG_WARN("unknown child (node=type): " + name + "\n");
401 }
402 }
403 return defaultArcType;
404}
405
406uint_fast64_t PnmlParser::traversePriority(xercesc::DOMNode const* const node) {
407 uint_fast64_t result = defaultPriority;
408 for (uint_fast64_t i = 0; i < node->getChildNodes()->getLength(); ++i) {
409 auto child = node->getChildNodes()->item(i);
410 auto name = storm::adapters::getName(child);
411 if (name == "text") {
412 result = std::stoull(storm::adapters::getName(child->getFirstChild()));
413 } else if (name == "value") {
414 auto value = storm::adapters::getName(child->getFirstChild());
415 value = value.substr(std::string("Default,").length());
416 result = std::stoull(value);
417 } else if (isOnlyWhitespace(name)) {
418 // ignore node (contains only whitespace)
419 } else if (name == "graphics") {
420 // ignore these tags
421 } else {
422 // Found node or attribute which is at the moment nod handled by this parser.
423 // Notify the user and continue the parsing.
424 STORM_LOG_WARN("unknown child (node=priority): " + name + "\n");
425 }
426 }
427 return result;
428}
429} // namespace parser
430} // namespace storm
431
432#endif
#define STORM_LOG_WARN(message)
Definition logging.h:28
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:28
Contains all file parsers and helper classes.