Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
AtomicPropositionLabelingParser.cpp
Go to the documentation of this file.
2
3#include <cstring>
4#include <iostream>
5#include <string>
6
12
13namespace storm {
14namespace parser {
15
16using namespace storm::utility::cstring;
17
19 // Open the given file.
20 MappedFile file(filename.c_str());
21 char const* buf = file.getData();
22
23 // First pass: Check whether we find declaration and end.
24 // TODO this could be skipped.
25 bool foundDecl = false, foundEnd = false;
26 size_t cnt = 0;
27
28 // Iterate over tokens until we hit #END or the end of the file.
29 while (buf[0] != '\0') {
30 // Move the buffer to the beginning of the next word.
31 buf += cnt;
32 buf = trimWhitespaces(buf);
33
34 // Get the number of characters until the next separator.
35 cnt = skipWord(buf) - buf;
36 if (cnt > 0) {
37 // If the next token is #DECLARATION: Just skip it.
38 // If the next token is #END: Stop the search.
39 // Otherwise increase proposition_count.
40 if (strncmp(buf, "#DECLARATION", cnt) == 0) {
41 foundDecl = true;
42 continue;
43 } else if (strncmp(buf, "#END", cnt) == 0) {
44 foundEnd = true;
45 break;
46 }
47 }
48 }
49
50 // If #DECLARATION or #END have not been found, the file format is wrong.
51 if (!(foundDecl && foundEnd)) {
52 STORM_LOG_ERROR("Error while parsing " << filename << ": File header is corrupted (#DECLARATION or #END missing - case sensitive).");
53 if (!foundDecl)
54 STORM_LOG_ERROR("\tDid not find #DECLARATION token.");
55 if (!foundEnd)
56 STORM_LOG_ERROR("\tDid not find #END token.");
57 throw storm::exceptions::WrongFormatException()
58 << "Error while parsing " << filename << ": File header is corrupted (#DECLARATION or #END missing - case sensitive).";
59 }
60
61 // Create labeling object with given node and proposition count.
62 storm::models::sparse::StateLabeling labeling(stateCount);
63
64 // Second pass: Add propositions and node labels to labeling.
65 // First thing to do: Reset the file pointer.
66 buf = file.getData();
67
68 // Prepare a buffer for proposition names.
69 char proposition[128];
70 cnt = 0;
71
72 // Parse proposition names.
73 // As we already checked the file header, we know that #DECLARATION and #END are tokens in the character stream.
74 while (buf[0] != '\0') {
75 // Move the buffer to the beginning of the next word.
76 buf += cnt;
77 buf = trimWhitespaces(buf);
78
79 // Get the number of characters until the next separator.
80 cnt = skipWord(buf) - buf;
81
82 if (cnt >= sizeof(proposition)) {
83 // if token is longer than our buffer, the following strncpy code might get risky...
84 STORM_LOG_ERROR("Error while parsing " << filename << ": Atomic proposition with length > " << (sizeof(proposition) - 1) << " was found.");
85 throw storm::exceptions::WrongFormatException()
86 << "Error while parsing " << filename << ": Atomic proposition with length > " << (sizeof(proposition) - 1) << " was found.";
87
88 } else if (cnt > 0) {
89 // If the next token is #DECLARATION: Just skip it.
90 if (strncmp(buf, "#DECLARATION", cnt) == 0)
91 continue;
92
93 // If the next token is #END: Stop the search.
94 if (strncmp(buf, "#END", cnt) == 0)
95 break;
96
97 // Otherwise copy the token to the buffer, append a trailing null byte and hand it to labeling.
98 strncpy(proposition, buf, cnt);
99 proposition[cnt] = '\0';
100 labeling.addLabel(proposition);
101 }
102 }
103
104 // At this point, the pointer buf is still pointing to our last token, i.e. to #END.
105 // We want to skip it.
106 buf += 4;
107
108 // Now eliminate remaining whitespaces such as empty lines and start parsing.
109 buf = trimWhitespaces(buf);
110
111 uint_fast64_t state = 0;
112 uint_fast64_t lastState = (uint_fast64_t)-1;
113 uint_fast64_t const startIndexComparison = lastState;
114 cnt = 0;
115
116 // Now parse the assignments of labels to nodes.
117 while (buf[0] != '\0') {
118 // Parse the state number and iterate over its labels (atomic propositions).
119 // Stop at the end of the line.
120 state = checked_strtol(buf, &buf);
121
122 // If the state has already been read or skipped once there might be a problem with the file (doubled lines, or blocks).
123 if (state <= lastState && lastState != startIndexComparison) {
124 STORM_LOG_ERROR("Error while parsing " << filename << ": State " << state << " was found but has already been read or skipped previously.");
125 throw storm::exceptions::WrongFormatException()
126 << "Error while parsing " << filename << ": State " << state << " was found but has already been read or skipped previously.";
127 }
128
129 while ((buf[0] != '\r') && (buf[0] != '\n') && (buf[0] != '\0')) {
130 cnt = skipWord(buf) - buf;
131 if (cnt == 0) {
132 // The next character is a separator.
133 // If it is a line separator, we continue with next node.
134 // Otherwise, we skip it and try again.
135 if (buf[0] == '\n' || buf[0] == '\r')
136 break;
137 buf++;
138 } else {
139 // Copy the label to the buffer, null terminate it and add it to labeling.
140 strncpy(proposition, buf, cnt);
141 proposition[cnt] = '\0';
142
143 // Has the label been declared in the header?
144 if (!labeling.containsLabel(proposition)) {
145 STORM_LOG_ERROR("Error while parsing " << filename << ": Atomic proposition" << proposition << " was found but not declared.");
146 throw storm::exceptions::WrongFormatException()
147 << "Error while parsing " << filename << ": Atomic proposition" << proposition << " was found but not declared.";
148 }
149 labeling.addLabelToState(proposition, state);
150 buf += cnt;
151 }
152 }
153 buf = trimWhitespaces(buf);
154 lastState = state;
155 }
156
157 return labeling;
158}
159
160} // namespace parser
161} // namespace storm
void addLabel(std::string const &label)
Adds a new label to the labelings.
bool containsLabel(std::string const &label) const
Checks whether a label is registered within this labeling.
This class manages the labeling of the state space with a number of (atomic) labels.
void addLabelToState(std::string const &label, storm::storage::sparse::state_type state)
Adds a label to a given state.
static storm::models::sparse::StateLabeling parseAtomicPropositionLabeling(uint_fast64_t stateCount, std::string const &filename)
Reads a label file and puts the result in an AtomicPropositionsLabeling object.
Opens a file and maps it to memory providing a char* containing the file content.
Definition MappedFile.h:21
char const * getData() const
Returns a pointer to the beginning of the mapped file data.
#define STORM_LOG_ERROR(message)
Definition logging.h:26
char const * skipWord(char const *buf)
Skips all numbers, letters and special characters.
Definition cstring.cpp:55
uint_fast64_t checked_strtol(char const *str, char const **end)
Calls strtol() internally and checks if the new pointer is different from the original one,...
Definition cstring.cpp:21
char const * trimWhitespaces(char const *buf)
Skips spaces, tabs, newlines and carriage returns.
Definition cstring.cpp:66