aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
O3prmReader_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2025 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40#pragma once
41
42
50#include <filesystem>
51
53
54namespace gum {
55 namespace prm {
56 namespace o3prm {
57
58 template < typename GUM_SCALAR >
59 INLINE std::string O3prmReader< GUM_SCALAR >::_clean_(std::string text) const {
60 // This could be way more faster with regex but there are not implemented
61 // with gcc-4.8 !
62 text = replace(text, "Syntax error", "Error");
63
64 text = replace(text, "LABEL_OR_STAR_LIST", "declaration");
65
66 text = replace(text, "ARRAY_REFERENCE_SLOT", "declaration");
67 text = replace(text, "FLOAT_AS_LABEL", "declaration");
68 text = replace(text, "FLOAT_OR_INT", "declaration");
69 text = replace(text, "INTEGER_AS_FLOAT", "declaration");
70 text = replace(text, "INTEGER_AS_LABEL", "declaration");
71 text = replace(text, "INT_TYPE_DECLARATION", "declaration");
72 text = replace(text, "LABEL_OR_INT", "declaration");
73 text = replace(text, "LABEL_OR_STAR", "declaration");
74 text = replace(text, "NAMED_CLASS_ELEMENT", "declaration");
75 text = replace(text, "REAL_TYPE_DECLARATION", "declaration");
76
77 text = replace(text, "AGGREGATE_PARENTS", "declaration");
78 text = replace(text, "CLASS_BODY", "declaration");
79 text = replace(text, "CLASS_DECLARATION", "declaration");
80 text = replace(text, "CLASS_ELEMENT", "declaration");
81 text = replace(text, "CLASS_PARAMETER", "declaration");
82 text = replace(text, "CLASS_UNIT", "declaration");
83 text = replace(text, "FLOAT_LIST", "declaration");
84 text = replace(text, "FORMULA_LIST", "declaration");
85 text = replace(text, "IDENTIFIER_LIST", "declaration");
86 text = replace(text, "IMPORT_BODY", "declaration");
87 text = replace(text, "IMPORT_DECLARATION", "declaration");
88 text = replace(text, "IMPORT_UNIT", "declaration");
89 text = replace(text, "INTERFACE_BODY", "declaration");
90 text = replace(text, "INTERFACE_DECLARATION", "declaration");
91 text = replace(text, "INTERFACE_UNIT", "declaration");
92 text = replace(text, "LABEL_LIST", "declaration");
93 text = replace(text, "PARAMETER_LIST", "declaration");
94 text = replace(text, "PREFIXED_LABEL", "declaration");
95 text = replace(text, "RAW_CPT", "declaration");
96 text = replace(text, "REFERENCE_SLOT", "declaration");
97 text = replace(text, "RULE_CPT", "declaration");
98 text = replace(text, "SYSTEM_BODY", "declaration");
99 text = replace(text, "SYSTEM_DECLARATION", "declaration");
100 text = replace(text, "SYSTEM_UNIT", "declaration");
101 text = replace(text, "TYPE_DECLARATION", "declaration");
102 text = replace(text, "TYPE_LABEL", "declaration");
103 text = replace(text, "TYPE_UNIT", "declaration");
104 text = replace(text, "TYPE_VALUE_LIST", "declaration");
105
106 text = replace(text, "AGGREGATE", "declaration");
107 text = replace(text, "ARRAY", "declaration");
108 text = replace(text, "ATTRIBUTE", "declaration");
109 text = replace(text, "CAST", "declaration");
110 text = replace(text, "CHAIN", "declaration");
111 text = replace(text, "CLASS", "declaration");
112 text = replace(text, "FLOAT", "declaration");
113 text = replace(text, "FORMULA", "declaration");
114 text = replace(text, "IDENTIFIER", "declaration");
115 text = replace(text, "INT", "declaration");
116 text = replace(text, "INTEGER", "declaration");
117 text = replace(text, "INTERFACE", "declaration");
118 text = replace(text, "LABEL", "declaration");
119 text = replace(text, "LINK", "declaration");
120 text = replace(text, "MAP", "declaration");
121 text = replace(text, "PARAMETER", "declaration");
122 text = replace(text, "REAL", "declaration");
123 text = replace(text, "RULE", "declaration");
124 text = replace(text, "TYPE", "declaration");
125 text = replace(text, "UNIT", "declaration");
126
127 return text;
128 }
129
130 template < typename GUM_SCALAR >
131 INLINE std::string O3prmReader< GUM_SCALAR >::_print_(const ParseError& err) const {
132 std::stringstream s;
133 s << err.filename << "|" << err.line << " col " << err.column << "| " << _clean_(err.msg);
134 return s.str();
135 }
137 template < typename GUM_SCALAR >
138 INLINE std::string O3prmReader< GUM_SCALAR >::_readStream_(std::istream& inputstr) {
139 if (inputstr) {
140 inputstr.seekg(0, inputstr.end);
141 int length = int(inputstr.tellg());
142 inputstr.seekg(0, inputstr.beg);
144 auto str = std::string();
145 str.resize(length, ' ');
146 auto begin = &*str.begin();
148 inputstr.read(begin, length);
149
150 return str;
151 }
152 GUM_ERROR(OperationNotAllowed, "Could not open file")
154
155 using o3prm_scanner = gum::prm::o3prm::Scanner;
156 using o3prm_parser = gum::prm::o3prm::Parser;
157
158 template < typename GUM_SCALAR >
160 _prm_(new PRM< GUM_SCALAR >()), _o3_prm_(std::unique_ptr< O3PRM >(new O3PRM())) {
161 GUM_CONSTRUCTOR(O3prmReader);
162 }
163
164 template < typename GUM_SCALAR >
166 _prm_(&prm), _o3_prm_(std::unique_ptr< O3PRM >(new O3PRM())) {
167 GUM_CONSTRUCTOR(O3prmReader);
169
170 template < typename GUM_SCALAR >
172 _prm_(src._prm_), _o3_prm_(std::unique_ptr< O3PRM >(new O3PRM(*(src._o3_prm_)))),
174 GUM_CONS_CPY(O3prmReader);
175 }
177 template < typename GUM_SCALAR >
179 _prm_(std::move(src._prm_)), _o3_prm_(std::move(src._o3_prm_)),
180 _class_path_(std::move(src._class_path_)), _imported_(std::move(src._imported_)),
181 _errors_(std::move(src._errors_)) {
182 GUM_CONS_CPY(O3prmReader);
183 }
184
185 template < typename GUM_SCALAR >
187 GUM_DESTRUCTOR(O3prmReader);
188 }
189
190 template < typename GUM_SCALAR >
193 if (this == &src) { return *this; }
194 _prm_ = src._prm_;
195 _o3_prm_ = std::unique_ptr< O3PRM >(new O3PRM(*(src._o3_prm_)));
198 _errors_ = src._errors_;
199 return *this;
200 }
201
202 template < typename GUM_SCALAR >
204 if (this == &src) { return *this; }
205 _prm_ = std::move(src._prm_);
206 _o3_prm_ = std::move(src._o3_prm_);
207 _class_path_ = std::move(src._class_path_);
208 _imported_ = std::move(src._imported_);
209 _errors_ = std::move(src._errors_);
210 return *this;
211 }
212
213 template < typename GUM_SCALAR >
214 void O3prmReader< GUM_SCALAR >::setClassPath(const std::string& class_path) {
215 _class_path_ = std::vector< std::string >();
216 size_t i = 0;
217 size_t j = class_path.find(';');
218
219 while (j != std::string::npos) {
220 addClassPath(class_path.substr(i, j - i));
221 i = j + 1;
222
223 if (i < class_path.size()) {
224 j = class_path.find(';', i);
225 } else {
226 j = std::string::npos;
227 }
228 }
229
230 if (i < class_path.size()) { addClassPath(class_path.substr(i, std::string::npos)); }
231 }
232
233 template < typename GUM_SCALAR >
234 void O3prmReader< GUM_SCALAR >::addClassPath(const std::string& class_path) {
235 auto path = class_path;
236 if (path[path.size() - 1] != '/') { path.append("/"); }
237 std::filesystem::directory_entry dir(path);
238 if (!dir.exists()) {
239 _errors_.addException("could not resolve class path", path);
240 } else {
241 _class_path_.push_back(std::move(path));
242 }
243 }
244
245 template < typename GUM_SCALAR >
247 return _errors_.error(i).line;
248 }
249
250 template < typename GUM_SCALAR >
252 return _errors_.error(i).column;
253 }
254
255 template < typename GUM_SCALAR >
256 INLINE std::wstring O3prmReader< GUM_SCALAR >::errFilename(Idx i) const {
257 return widen(_errors_.error(i).filename);
258 }
259
260 template < typename GUM_SCALAR >
262 return _errors_.error(i).is_error;
263 }
264
265 template < typename GUM_SCALAR >
266 INLINE std::string O3prmReader< GUM_SCALAR >::errMsg(Idx i) const {
267 return _errors_.error(i).msg;
268 }
269
270 template < typename GUM_SCALAR >
271 INLINE void O3prmReader< GUM_SCALAR >::showElegantErrors(std::ostream& o) const {
272 for (Idx i = 0; i < _errors_.count(); ++i) {
273 auto err = _errors_.error(i);
274 if (err.is_error) { o << _print_(err) << std::endl; }
275 }
276 }
277
278 template < typename GUM_SCALAR >
280 for (Idx i = 0; i < _errors_.count(); ++i) {
281 auto err = _errors_.error(i);
282 o << _print_(err) << std::endl;
283 }
284 }
285
286 template < typename GUM_SCALAR >
287 INLINE void O3prmReader< GUM_SCALAR >::showErrorCounts(std::ostream& o) const {
288 _errors_.syntheticResults(o);
289 }
290
291 template < typename GUM_SCALAR >
293 return _errors_.error_count;
294 }
295
296 template < typename GUM_SCALAR >
298 return _errors_.warning_count;
299 }
300
301 template < typename GUM_SCALAR >
303 return _errors_;
304 }
305
306 template < typename GUM_SCALAR >
307 INLINE Size O3prmReader< GUM_SCALAR >::readString(const std::string& str) {
308 std::stringstream sBuff(str);
309 _readStream_(sBuff, "");
310 return _errors_.count();
311 }
312
313 template < typename GUM_SCALAR >
314 INLINE Size O3prmReader< GUM_SCALAR >::readFile(const std::string& file,
315 const std::string& module) {
316 try {
317 auto const lastSlashIndex = file.find_last_of('/');
318
319 std::filesystem::directory_entry dir(file.substr(0, lastSlashIndex + 1));
320 if (!dir.exists()) {
321 _errors_.addException("could not find file", file);
322 return _errors_.count();
323 }
324
325 auto const basename = file.substr(lastSlashIndex + 1);
326 auto const absFilename
327 = std::filesystem::absolute(dir.path() / std::filesystem::path(basename)).string();
328
329 std::ifstream input(absFilename);
330 if (input.is_open()) {
331 _readStream_(input, file, module);
332 } else {
333 _errors_.addException("could not open file", file);
334 }
335
336 return _errors_.count();
337
338 } catch (gum::Exception& e) {
339 GUM_SHOWERROR(e);
340 _errors_.addException(e.errorContent(), file);
341 return _errors_.count();
342 } catch (...) {
343 _errors_.addException("unknown error", file);
344 return _errors_.count();
345 }
346 }
347
348 template < typename GUM_SCALAR >
349 INLINE void O3prmReader< GUM_SCALAR >::parseStream(std::istream& input,
350 std::ostream& output,
351 std::string module) {
352 _readStream_(input, "", module);
353
355 }
356
357 template < typename GUM_SCALAR >
358 INLINE void O3prmReader< GUM_SCALAR >::_parseStream_(std::istream& input,
359 const std::string& filename,
360 const std::string& module) {
361 auto sBuff = _readStream_(input);
362 auto buffer = std::unique_ptr< unsigned char[] >(new unsigned char[sBuff.length() + 1]);
363 strcpy((char*)buffer.get(), sBuff.c_str());
364 auto s = o3prm_scanner(buffer.get(), int(sBuff.length() + 1), filename);
365 auto p = o3prm_parser(&s);
366 p.set_prm(_o3_prm_.get());
367 p.set_prefix(module);
368 p.Parse();
369 _errors_ += p.errors();
370 }
371
372 template < typename GUM_SCALAR >
374 const std::string& module) {
375 if (!_imported_.exists(i.import().label())) {
376 _imported_.insert(i.import().label());
377
378 auto module_path = module;
379 std::replace(module_path.begin(), module_path.end(), '.', '/');
380
381 auto path = i.import().label();
382 std::replace(path.begin(), path.end(), '.', '/');
383
384 auto imported = false;
385 for (const auto& cp: _class_path_) {
386 auto file_path = cp + path + ".o3prm";
387 std::ifstream file(file_path);
388
389 if (file.is_open()) {
390 _parseStream_(file, file_path, i.import().label());
391 imported = true;
392 break;
393 }
394
395 file_path = cp + module + path + ".o3prm";
396 std::ifstream file2(file_path);
397
398 if (file2.is_open()) {
399 _parseStream_(file2, file_path, module + "." + i.import().label());
400 imported = true;
401 break;
402 }
403 }
404
405 if (!imported) {
406 const auto& pos = i.import().position();
407 std::stringstream msg;
408 msg << "Import error: could not resolve import " << i.import().label();
409 _errors_.addError(msg.str(), pos.file(), pos.line(), pos.column());
410 }
411 }
412 }
413
414 template < typename GUM_SCALAR >
415 INLINE std::vector< const O3Import* > O3prmReader< GUM_SCALAR >::_copyImports_() {
416 auto copy = std::vector< const O3Import* >();
417 for (const auto& i: _o3_prm_->imports()) {
418 if (!_imported_.exists(i->import().label())) { copy.push_back(i.get()); }
419 }
420 return copy;
421 }
422
423 template < typename GUM_SCALAR >
424 INLINE void O3prmReader< GUM_SCALAR >::_readStream_(std::istream& input,
425 const std::string& file,
426 std::string module) {
427 if (module.size() > 0 && module.back() != '.') { module.append("."); }
428
429 _parseStream_(input, file, module);
430
431 auto imports = _copyImports_();
432 do {
433 for (auto i: imports) {
434 _parseImport_(*i, module);
435 }
436 imports = _copyImports_();
437 } while (imports.size() > 0);
438
439
440 if (_errors_.error_count == 0) {
442 auto type_factory = O3TypeFactory< GUM_SCALAR >(*_prm_, *_o3_prm_, solver, _errors_);
443
444 auto interface_factory
446 auto class_factory = O3ClassFactory< GUM_SCALAR >(*_prm_, *_o3_prm_, solver, _errors_);
447
448 auto system_factory = O3SystemFactory< GUM_SCALAR >(*_prm_, *_o3_prm_, solver, _errors_);
449
450 try {
451 type_factory.build();
452 interface_factory.buildInterfaces();
453 class_factory.buildClasses();
454 interface_factory.buildElements();
455 class_factory.buildImplementations();
456 class_factory.buildParameters();
457 class_factory.buildReferenceSlots();
458 class_factory.declareAttributes();
459 class_factory.declareAggregates();
460 class_factory.completeAggregates();
461 class_factory.completeAttributes();
462 system_factory.build();
463 } catch (Exception const&) {
464 if (_errors_.count() == 0) { _errors_.addException("an unknown error occured", file); }
465 } catch (...) { _errors_.addException("an unknown exception occured", file); }
466 }
467 }
468 } // namespace o3prm
469 } // namespace prm
470} // namespace gum
Headers for the O3prmReader class.
std::wstring widen(const std::string &str)
Cast a std::string into a std::wstring.
This class is used contain and manipulate gum::ParseError.
Base class for all aGrUM's exceptions.
Definition exceptions.h:118
GUM_NODISCARD std::string errorContent() const
Returns the message content.
Definition exceptions.h:144
Exception : operation not allowed.
This class is used to represent parsing errors for the different parser implemented in aGrUM.
std::string filename
The file of this gum::ParseError, default is "".
Idx column
The column of this gum::ParseError, default is 0.
std::string msg
The gum::ParseError message.
Idx line
The line of this gum::ParseError.
bool is_error
If false, this gum::ParseError is a warning.
This class represents a Probabilistic Relational PRMSystem<GUM_SCALAR>.
Definition PRM.h:74
Builds gum::prm::Class from gum::prm::o3prm::O3Class.
The O3Import is part of the AST of the O3PRM language.
Definition O3prm.h:889
Bulds gum::prm:PRMInterface from gum::prm::o3prm::O3Interface.
std::string & label()
Definition O3prm.cpp:287
O3Position & position()
Definition O3prm.cpp:283
Resolves names for the different O3PRM factories.
The O3PRM is part of the AST of the O3PRM language.
Definition O3prm.h:913
Builds gum::prm::PRMSystem from gum::prm::o3prm::O3System.
Builds gum::prm::PRMType from gum::prm::o3prm::O3Type, gum::prm::o3prm::O3IntType and gum::prm::o3prm...
This class read O3PRM files and creates the corresponding gum::prm::PRM.
Definition O3prmReader.h:84
Size errors() const
publishing Errors API
std::vector< const O3Import * > _copyImports_()
Size readString(const std::string &string)
With readString method, you must set the current path to search from import yourself,...
void _parseImport_(const O3Import &i, const std::string &module_path)
const ErrorsContainer & errorsContainer() const
publishing Errors API
std::wstring errFilename(Idx i) const
filename of ith error or warning
void showElegantErrors(std::ostream &o=std::cerr) const
send on std::cerr the list of errors
void addClassPath(const std::string &class_path)
Add a list of paths to look for o3prm files.
Idx errCol(Idx i) const
col of ith error or warning
std::string _print_(const ParseError &err) const
gum::prm::PRM< GUM_SCALAR > * prm()
void setClassPath(const std::string &class_path)
This methods defines the list of paths to look for o3prm files.
void showErrorCounts(std::ostream &o=std::cerr) const
send on std::cerr the number of errors and the number of warnings
void showElegantErrorsAndWarnings(std::ostream &o=std::cerr) const
send on std::cerr the list of errors or warnings
O3prmReader & operator=(const O3prmReader &src)
void _readStream_(std::istream &input, const std::string &file, std::string module="")
void _parseStream_(std::istream &input, const std::string &filename, const std::string &module)
bool errIsError(Idx i) const
type of ith error or warning
Idx errLine(Idx i) const
line of ith error or warning
void parseStream(std::istream &input, std::ostream &output, std::string module="")
std::string errMsg(Idx i) const
message of ith error or warning
Size readFile(const std::string &file, const std::string &module="")
Read file and load its content using a PRMFactory. The package parameter set the file's content packa...
std::string _clean_(std::string text) const
std::unique_ptr< O3PRM > _o3_prm_
PRM< GUM_SCALAR > * _prm_
std::vector< std::string > _class_path_
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
#define GUM_SHOWERROR(e)
Definition exceptions.h:85
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
std::string replace(const std::string &s, const std::string &val, const std::string &new_val)
not usable for gcc 4.8 std::vector<std::string> split( const std::string& orig, ...
gum::prm::o3prm::Scanner o3prm_scanner
gum::prm::o3prm::Parser o3prm_parser
namespace for all probabilistic relational models entities
Definition agrum.h:68
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
STL namespace.