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