OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
simple_parser.hpp
Go to the documentation of this file.
1//
2// Simple recursive descent parser for SDDS format
3// Replaces boost::spirit::qi parser
4//
5// Copyright (c) 2024
6// All rights reserved
7//
8#ifndef SIMPLE_PARSER_HPP_
9#define SIMPLE_PARSER_HPP_
10
11#include "array.hpp"
12#include "associate.hpp"
13#include "ast.hpp"
14#include "column.hpp"
15#include "data.hpp"
16#include "description.hpp"
17#include "include.hpp"
18#include "parameter.hpp"
19#include "version.hpp"
20
21#include <cctype>
22#include <sstream>
23#include <stdexcept>
24#include <string>
25
26namespace SDDS {
27 namespace parser {
28
30 public:
31 SimpleParser(const std::string& input) : input_(input), pos_(0) {}
32
34 file result;
36
37 // Parse version
38 result.sddsVersion_m = parseVersion();
40
41 // Parse optional description
42 if (match("&description")) {
45 }
46
47 // Parse parameters, columns, associates, arrays, includes
48 while (pos_ < input_.length()) {
50 if (match("&parameter")) {
51 result.sddsParameters_m.push_back(parseParameter());
52 } else if (match("&column")) {
53 result.sddsColumns_m.push_back(parseColumn());
54 } else if (match("&associate")) {
55 result.sddsAssociates_m.push_back(parseAssociate());
56 } else if (match("&array")) {
57 result.sddsArrays_m.push_back(parseArray());
58 } else if (match("&include")) {
59 result.sddsIncludes_m.push_back(parseInclude());
60 } else if (match("&data")) {
61 result.sddsData_m = parseData();
62 break;
63 } else {
64 break;
65 }
67 }
68
69 return result;
70 }
71
72 private:
73 std::string input_;
74 size_t pos_;
75
77 while (pos_ < input_.length()) {
78 if (std::isspace(static_cast<unsigned char>(input_[pos_]))) {
79 pos_++;
80 } else if (input_[pos_] == '!') {
81 // Skip comments
82 while (pos_ < input_.length() && input_[pos_] != '\n') {
83 pos_++;
84 }
85 } else {
86 break;
87 }
88 }
89 }
90
91 bool match(const std::string& str) {
93 if (input_.compare(pos_, str.length(), str) == 0) {
94 pos_ += str.length();
95 return true;
96 }
97 return false;
98 }
99
100 bool match(char c) {
102 if (pos_ < input_.length() && input_[pos_] == c) {
103 pos_++;
104 return true;
105 }
106 return false;
107 }
108
109 void expect(const std::string& str) {
110 if (!match(str)) {
111 throw std::runtime_error("Expected: " + str);
112 }
113 }
114
115 void expect(char c) {
116 if (!match(c)) {
117 throw std::runtime_error(std::string("Expected: ") + c);
118 }
119 }
120
121 std::string parseQuotedString() {
122 if (pos_ >= input_.length() || input_[pos_] != '"') {
123 return "";
124 }
125 pos_++; // skip opening quote
126 std::string result;
127 while (pos_ < input_.length() && input_[pos_] != '"') {
128 if (input_[pos_] == '\\' && pos_ + 1 < input_.length()) {
129 pos_++;
130 result += input_[pos_];
131 } else {
132 result += input_[pos_];
133 }
134 pos_++;
135 }
136 if (pos_ < input_.length() && input_[pos_] == '"') {
137 pos_++; // skip closing quote
138 }
139 return result;
140 }
141
142 std::string parseIdentifier() {
144 std::string result;
145 while (pos_ < input_.length()) {
146 char c = input_[pos_];
147 if (std::isalnum(static_cast<unsigned char>(c)) || c == '@' || c == '#'
148 || c == ':' || c == '+' || c == '-' || c == '%' || c == '.' || c == '_'
149 || c == '$' || c == '&' || c == '/') {
150 result += c;
151 pos_++;
152 } else {
153 break;
154 }
155 }
156 return result;
157 }
158
159 std::string parseString() {
161 if (pos_ < input_.length() && input_[pos_] == '"') {
162 return parseQuotedString();
163 }
164 return parseIdentifier();
165 }
166
168 version v;
169 expect("SDDS");
171 std::string numStr;
172 while (pos_ < input_.length()
173 && std::isdigit(static_cast<unsigned char>(input_[pos_]))) {
174 numStr += input_[pos_];
175 pos_++;
176 }
177 if (numStr.empty()) {
178 throw std::runtime_error("Expected version number");
179 }
180 v.layoutVersion_m = static_cast<short>(std::stoi(numStr));
181 return v;
182 }
183
185 description desc;
187
188 while (pos_ < input_.length() && !match("&end")) {
190 if (match("text")) {
191 expect('=');
192 desc.text_m = parseString();
194 if (match(',')) skipWhitespace();
195 } else if (match("contents")) {
196 expect('=');
197 desc.content_m = parseString();
199 if (match(',')) skipWhitespace();
200 } else {
201 break;
202 }
203 }
204 expect("&end");
205 return desc;
206 }
207
209 parameter param;
211
212 while (pos_ < input_.length() && !match("&end")) {
214 if (match("name")) {
215 expect('=');
216 param.name_m = parseString();
218 if (match(',')) skipWhitespace();
219 } else if (match("type")) {
220 expect('=');
221 std::string typeStr = parseString();
222 if (typeStr == "float")
223 param.type_m = ast::FLOAT;
224 else if (typeStr == "double")
225 param.type_m = ast::DOUBLE;
226 else if (typeStr == "short")
227 param.type_m = ast::SHORT;
228 else if (typeStr == "long")
229 param.type_m = ast::LONG;
230 else if (typeStr == "character")
231 param.type_m = ast::CHARACTER;
232 else if (typeStr == "string")
233 param.type_m = ast::STRING;
235 if (match(',')) skipWhitespace();
236 } else if (match("units")) {
237 expect('=');
238 param.units_m = parseString();
240 if (match(',')) skipWhitespace();
241 } else if (match("description")) {
242 expect('=');
243 param.description_m = parseString();
245 if (match(',')) skipWhitespace();
246 } else {
247 // Skip unsupported fields
248 parseString();
250 if (match(',')) skipWhitespace();
251 }
252 }
253 expect("&end");
254 return param;
255 }
256
258 column col;
260
261 while (pos_ < input_.length() && !match("&end")) {
263 if (match("name")) {
264 expect('=');
265 col.name_m = parseString();
267 if (match(',')) skipWhitespace();
268 } else if (match("type")) {
269 expect('=');
270 std::string typeStr = parseString();
271 if (typeStr == "float")
272 col.type_m = ast::FLOAT;
273 else if (typeStr == "double")
274 col.type_m = ast::DOUBLE;
275 else if (typeStr == "short")
276 col.type_m = ast::SHORT;
277 else if (typeStr == "long")
278 col.type_m = ast::LONG;
279 else if (typeStr == "character")
281 else if (typeStr == "string")
282 col.type_m = ast::STRING;
284 if (match(',')) skipWhitespace();
285 } else if (match("units")) {
286 expect('=');
287 col.units_m = parseString();
289 if (match(',')) skipWhitespace();
290 } else if (match("description")) {
291 expect('=');
294 if (match(',')) skipWhitespace();
295 } else {
296 // Skip unsupported fields
297 parseString();
299 if (match(',')) skipWhitespace();
300 }
301 }
302 expect("&end");
303 return col;
304 }
305
307 associate assoc;
309 // Basic implementation - can be extended
310 while (pos_ < input_.length() && !match("&end")) {
312 parseString(); // Skip content for now
314 if (match(',')) skipWhitespace();
315 }
316 expect("&end");
317 return assoc;
318 }
319
321 array arr;
323 // Basic implementation - can be extended
324 while (pos_ < input_.length() && !match("&end")) {
326 parseString(); // Skip content for now
328 if (match(',')) skipWhitespace();
329 }
330 expect("&end");
331 return arr;
332 }
333
335 include inc;
337 // Basic implementation - can be extended
338 while (pos_ < input_.length() && !match("&end")) {
340 parseString(); // Skip content for now
342 if (match(',')) skipWhitespace();
343 }
344 expect("&end");
345 return inc;
346 }
347
349 data d;
351 // Parse data mode
352 if (match("mode")) {
353 expect('=');
354 std::string modeStr = parseString();
355 if (modeStr == "ascii")
356 d.mode_m = ast::ASCII;
357 else if (modeStr == "binary")
360 if (match(',')) skipWhitespace();
361 }
362 if (match("no_row_counts")) {
363 expect('=');
364 std::string val = parseString();
365 // Parse boolean value
367 if (match(',')) skipWhitespace();
368 }
369 expect("&end");
371
372 // Parse data rows (simplified - actual parsing would be more complex)
373 // This is a placeholder - the actual data parsing is done separately
374 // in the original code via parameter::parse() and column::parse()
375
376 return d;
377 }
378 };
379
380 } // namespace parser
381} // namespace SDDS
382
383#endif /* SIMPLE_PARSER_HPP_ */
bool match(const std::string &str)
SimpleParser(const std::string &input)
void expect(const std::string &str)
@ ASCII
Definition ast.hpp:28
@ BINARY
Definition ast.hpp:28
@ STRING
Definition ast.hpp:26
@ DOUBLE
Definition ast.hpp:26
@ LONG
Definition ast.hpp:26
@ FLOAT
Definition ast.hpp:26
@ CHARACTER
Definition ast.hpp:26
@ SHORT
Definition ast.hpp:26
std::optional< std::string > content_m
short layoutVersion_m
Definition version.hpp:26
std::optional< std::string > text_m
std::optional< std::string > name_m
Definition column.hpp:34
std::optional< ast::datatype > type_m
Definition column.hpp:37
std::optional< std::string > units_m
Definition column.hpp:35
std::optional< std::string > description_m
Definition column.hpp:36
ast::datamode mode_m
Definition data.hpp:36
version sddsVersion_m
Definition file.hpp:36
std::optional< description > sddsDescription_m
Definition file.hpp:37
columnList sddsColumns_m
Definition file.hpp:39
arrayList sddsArrays_m
Definition file.hpp:42
data sddsData_m
Definition file.hpp:40
includeList sddsIncludes_m
Definition file.hpp:43
parameterList sddsParameters_m
Definition file.hpp:38
associateList sddsAssociates_m
Definition file.hpp:41
std::optional< std::string > name_m
Definition parameter.hpp:34
std::optional< std::string > description_m
Definition parameter.hpp:36
std::optional< std::string > units_m
Definition parameter.hpp:35
std::optional< ast::datatype > type_m
Definition parameter.hpp:37