aGrUM 3.1.1
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-2026 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-2026 *
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
41#pragma once
42
43
51#include <filesystem>
52
54
55namespace gum {
56 namespace prm {
57 namespace o3prm {
58
59 template < GUM_Numeric GUM_SCALAR >
60 std::string O3prmReader< GUM_SCALAR >::_clean_(std::string text) const {
61 // This could be way more faster with regex but there are not implemented
62 // with gcc-4.8 !
63 text = replace(text, "Syntax error", "Error");
64
65 text = replace(text, "LABEL_OR_STAR_LIST", "declaration");
66
67 text = replace(text, "ARRAY_REFERENCE_SLOT", "declaration");
68 text = replace(text, "FLOAT_AS_LABEL", "declaration");
69 text = replace(text, "FLOAT_OR_INT", "declaration");
70 text = replace(text, "INTEGER_AS_FLOAT", "declaration");
71 text = replace(text, "INTEGER_AS_LABEL", "declaration");
72 text = replace(text, "INT_TYPE_DECLARATION", "declaration");
73 text = replace(text, "LABEL_OR_INT", "declaration");
74 text = replace(text, "LABEL_OR_STAR", "declaration");
75 text = replace(text, "NAMED_CLASS_ELEMENT", "declaration");
76 text = replace(text, "REAL_TYPE_DECLARATION", "declaration");
77
78 text = replace(text, "AGGREGATE_PARENTS", "declaration");
79 text = replace(text, "CLASS_BODY", "declaration");
80 text = replace(text, "CLASS_DECLARATION", "declaration");
81 text = replace(text, "CLASS_ELEMENT", "declaration");
82 text = replace(text, "CLASS_PARAMETER", "declaration");
83 text = replace(text, "CLASS_UNIT", "declaration");
84 text = replace(text, "FLOAT_LIST", "declaration");
85 text = replace(text, "FORMULA_LIST", "declaration");
86 text = replace(text, "IDENTIFIER_LIST", "declaration");
87 text = replace(text, "IMPORT_BODY", "declaration");
88 text = replace(text, "IMPORT_DECLARATION", "declaration");
89 text = replace(text, "IMPORT_UNIT", "declaration");
90 text = replace(text, "INTERFACE_BODY", "declaration");
91 text = replace(text, "INTERFACE_DECLARATION", "declaration");
92 text = replace(text, "INTERFACE_UNIT", "declaration");
93 text = replace(text, "LABEL_LIST", "declaration");
94 text = replace(text, "PARAMETER_LIST", "declaration");
95 text = replace(text, "PREFIXED_LABEL", "declaration");
96 text = replace(text, "RAW_CPT", "declaration");
97 text = replace(text, "REFERENCE_SLOT", "declaration");
98 text = replace(text, "RULE_CPT", "declaration");
99 text = replace(text, "SYSTEM_BODY", "declaration");
100 text = replace(text, "SYSTEM_DECLARATION", "declaration");
101 text = replace(text, "SYSTEM_UNIT", "declaration");
102 text = replace(text, "TYPE_DECLARATION", "declaration");
103 text = replace(text, "TYPE_LABEL", "declaration");
104 text = replace(text, "TYPE_UNIT", "declaration");
105 text = replace(text, "TYPE_VALUE_LIST", "declaration");
106
107 text = replace(text, "AGGREGATE", "declaration");
108 text = replace(text, "ARRAY", "declaration");
109 text = replace(text, "ATTRIBUTE", "declaration");
110 text = replace(text, "CAST", "declaration");
111 text = replace(text, "CHAIN", "declaration");
112 text = replace(text, "CLASS", "declaration");
113 text = replace(text, "FLOAT", "declaration");
114 text = replace(text, "FORMULA", "declaration");
115 text = replace(text, "IDENTIFIER", "declaration");
116 text = replace(text, "INT", "declaration");
117 text = replace(text, "INTEGER", "declaration");
118 text = replace(text, "INTERFACE", "declaration");
119 text = replace(text, "LABEL", "declaration");
120 text = replace(text, "LINK", "declaration");
121 text = replace(text, "MAP", "declaration");
122 text = replace(text, "PARAMETER", "declaration");
123 text = replace(text, "REAL", "declaration");
124 text = replace(text, "RULE", "declaration");
125 text = replace(text, "TYPE", "declaration");
126 text = replace(text, "UNIT", "declaration");
127
128 return text;
129 }
130
131 template < GUM_Numeric GUM_SCALAR >
132 std::string O3prmReader< GUM_SCALAR >::_print_(const ParseError& err) const {
133 return std::format("{}|{} col {}| {}",
134 err.filename,
135 err.line,
136 err.column,
137 _clean_(err.msg));
139
140 template < GUM_Numeric GUM_SCALAR >
141 std::string O3prmReader< GUM_SCALAR >::_readStream_(std::istream& inputstr) {
142 if (inputstr) {
143 inputstr.seekg(0, inputstr.end);
144 int length = int(inputstr.tellg());
145 inputstr.seekg(0, inputstr.beg);
146
147 auto str = std::string();
148 str.resize(length, ' ');
149 auto begin = &*str.begin();
150
151 inputstr.read(begin, length);
153 return str;
154 }
155 GUM_ERROR(OperationNotAllowed, "Could not open file")
156 }
157
158 using o3prm_scanner = gum::prm::o3prm::Scanner;
159 using o3prm_parser = gum::prm::o3prm::Parser;
160
161 template < GUM_Numeric GUM_SCALAR >
163 _prm_(new PRM< GUM_SCALAR >()), _o3_prm_(std::unique_ptr< O3PRM >(new O3PRM())) {
164 GUM_CONSTRUCTOR(O3prmReader);
165 }
166
167 template < GUM_Numeric GUM_SCALAR >
169 _prm_(&prm), _o3_prm_(std::unique_ptr< O3PRM >(new O3PRM())) {
170 GUM_CONSTRUCTOR(O3prmReader);
171 }
173 template < GUM_Numeric GUM_SCALAR >
175 _prm_(src._prm_), _o3_prm_(std::unique_ptr< O3PRM >(new O3PRM(*(src._o3_prm_)))),
177 GUM_CONS_CPY(O3prmReader);
179
180 template < GUM_Numeric GUM_SCALAR >
182 _prm_(std::move(src._prm_)), _o3_prm_(std::move(src._o3_prm_)),
183 _class_path_(std::move(src._class_path_)), _imported_(std::move(src._imported_)),
184 _errors_(std::move(src._errors_)) {
185 GUM_CONS_CPY(O3prmReader);
186 }
187
188 template < GUM_Numeric GUM_SCALAR >
192
193 template < GUM_Numeric GUM_SCALAR >
195 if (this == &src) { return *this; }
196 _prm_ = src._prm_;
197 _o3_prm_ = std::unique_ptr< O3PRM >(new O3PRM(*(src._o3_prm_)));
200 _errors_ = src._errors_;
201 return *this;
202 }
203
204 template < GUM_Numeric GUM_SCALAR >
206 if (this == &src) { return *this; }
207 _prm_ = std::move(src._prm_);
208 _o3_prm_ = std::move(src._o3_prm_);
209 _class_path_ = std::move(src._class_path_);
210 _imported_ = std::move(src._imported_);
211 _errors_ = std::move(src._errors_);
212 return *this;
213 }
214
215 template < GUM_Numeric GUM_SCALAR >
216 void O3prmReader< GUM_SCALAR >::setClassPath(std::string_view class_path) {
217 _class_path_ = std::vector< std::string >();
218 size_t i = 0;
219 size_t j = class_path.find(';');
220
221 while (j != std::string::npos) {
222 addClassPath(class_path.substr(i, j - i));
223 i = j + 1;
224
225 if (i < class_path.size()) {
226 j = class_path.find(';', i);
227 } else {
228 j = std::string::npos;
229 }
230 }
231
232 if (i < class_path.size()) { addClassPath(class_path.substr(i, std::string::npos)); }
233 }
234
235 template < GUM_Numeric GUM_SCALAR >
236 void O3prmReader< GUM_SCALAR >::addClassPath(std::string_view class_path) {
237 std::string path(class_path);
238 if (path[path.size() - 1] != '/') { path.append("/"); }
239 std::filesystem::directory_entry dir(path);
240 if (!dir.exists()) {
241 _errors_.addException("could not resolve class path", path);
242 } else {
243 _class_path_.push_back(std::move(path));
244 }
245 }
246
247 template < GUM_Numeric GUM_SCALAR >
249 return _errors_.error(i).line;
250 }
251
252 template < GUM_Numeric GUM_SCALAR >
254 return _errors_.error(i).column;
255 }
256
257 template < GUM_Numeric GUM_SCALAR >
259 return widen(_errors_.error(i).filename);
260 }
261
262 template < GUM_Numeric GUM_SCALAR >
264 return _errors_.error(i).is_error;
265 }
266
267 template < GUM_Numeric GUM_SCALAR >
269 return _errors_.error(i).msg;
270 }
271
272 template < GUM_Numeric GUM_SCALAR >
274 for (Idx i = 0; i < _errors_.count(); ++i) {
275 auto err = _errors_.error(i);
276 if (err.is_error) { o << _print_(err) << std::endl; }
277 }
278 }
279
280 template < GUM_Numeric GUM_SCALAR >
282 for (Idx i = 0; i < _errors_.count(); ++i) {
283 auto err = _errors_.error(i);
284 o << _print_(err) << std::endl;
285 }
286 }
287
288 template < GUM_Numeric GUM_SCALAR >
289 void O3prmReader< GUM_SCALAR >::showErrorCounts(std::ostream& o) const {
290 _errors_.syntheticResults(o);
291 }
292
293 template < GUM_Numeric GUM_SCALAR >
295 return _errors_.error_count;
296 }
297
298 template < GUM_Numeric GUM_SCALAR >
300 return _errors_.warning_count;
301 }
302
303 template < GUM_Numeric GUM_SCALAR >
307
308 template < GUM_Numeric GUM_SCALAR >
310 std::stringstream sBuff(str);
311 _readStream_(sBuff, "");
312 return _errors_.count();
313 }
314
315 template < GUM_Numeric GUM_SCALAR >
316 Size O3prmReader< GUM_SCALAR >::readFile(std::string_view file, std::string_view module) {
317 try {
318 auto const lastSlashIndex = file.find_last_of('/');
319
320 std::filesystem::directory_entry dir(file.substr(0, lastSlashIndex + 1));
321 if (!dir.exists()) {
322 _errors_.addException("could not find file", file);
323 return _errors_.count();
324 }
325
326 auto const basename = file.substr(lastSlashIndex + 1);
327 auto const absFilename
328 = std::filesystem::absolute(dir.path() / std::filesystem::path(basename)).string();
329
330 std::ifstream input(absFilename);
331 if (input.is_open()) {
332 _readStream_(input, std::string(file), std::string(module));
333 } else {
334 _errors_.addException("could not open file", file);
335 }
336
337 return _errors_.count();
338
339 } catch (gum::Exception& e) {
340 GUM_SHOWERROR(e);
341 _errors_.addException(e.errorContent(), file);
342 return _errors_.count();
343 } catch (...) {
344 _errors_.addException("unknown error", file);
345 return _errors_.count();
346 }
347 }
348
349 template < GUM_Numeric GUM_SCALAR >
351 std::ostream& output,
352 std::string module) {
353 _readStream_(input, "", module);
354
356 }
357
358 template < GUM_Numeric GUM_SCALAR >
360 const std::string& filename,
361 const std::string& module) {
362 auto sBuff = _readStream_(input);
363 auto buffer = std::unique_ptr< unsigned char[] >(new unsigned char[sBuff.length() + 1]);
364 strcpy((char*)buffer.get(), sBuff.c_str());
365 auto s = o3prm_scanner(buffer.get(), int(sBuff.length() + 1), filename);
366 auto p = o3prm_parser(&s);
367 p.set_prm(_o3_prm_.get());
368 p.set_prefix(module);
369 p.Parse();
370 _errors_ += p.errors();
371 }
372
373 template < GUM_Numeric GUM_SCALAR >
374 void O3prmReader< GUM_SCALAR >::_parseImport_(const O3Import& i, 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 _errors_.addError(
408 std::format("Import error: could not resolve import {}", i.import().label()),
409 pos.file(),
410 pos.line(),
411 pos.column());
412 }
413 }
414 }
415
416 template < GUM_Numeric GUM_SCALAR >
417 std::vector< const O3Import* > O3prmReader< GUM_SCALAR >::_copyImports_() {
418 auto copy = std::vector< const O3Import* >();
419 for (const auto& i: _o3_prm_->imports()) {
420 if (!_imported_.exists(i->import().label())) { copy.push_back(i.get()); }
421 }
422 return copy;
423 }
424
425 template < GUM_Numeric GUM_SCALAR >
427 const std::string& file,
428 std::string module) {
429 if (module.size() > 0 && module.back() != '.') { module.append("."); }
430
431 _parseStream_(input, file, module);
432
433 auto imports = _copyImports_();
434 do {
435 for (auto i: imports) {
436 _parseImport_(*i, module);
437 }
438 imports = _copyImports_();
439 } while (imports.size() > 0);
440
441
442 if (_errors_.error_count == 0) {
444 auto type_factory = O3TypeFactory< GUM_SCALAR >(*_prm_, *_o3_prm_, solver, _errors_);
445
446 auto interface_factory
448 auto class_factory = O3ClassFactory< GUM_SCALAR >(*_prm_, *_o3_prm_, solver, _errors_);
449
450 auto system_factory = O3SystemFactory< GUM_SCALAR >(*_prm_, *_o3_prm_, solver, _errors_);
451
452 try {
453 type_factory.build();
454 interface_factory.buildInterfaces();
455 class_factory.buildClasses();
456 interface_factory.buildElements();
457 class_factory.buildImplementations();
458 class_factory.buildParameters();
459 class_factory.buildReferenceSlots();
460 class_factory.declareAttributes();
461 class_factory.declareAggregates();
462 class_factory.completeAggregates();
463 class_factory.completeAttributes();
464 system_factory.build();
465 } catch (Exception const&) {
466 if (_errors_.count() == 0) { _errors_.addException("an unknown error occured", file); }
467 } catch (...) { _errors_.addException("an unknown exception occured", file); }
468 }
469 }
470
471 template < GUM_Numeric GUM_SCALAR >
475
476 template < GUM_Numeric GUM_SCALAR >
480
481 } // namespace o3prm
482 } // namespace prm
483} // namespace gum
Headers for the O3prmReader class.
std::wstring widen(std::string_view 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:122
GUM_NODISCARD std::string errorContent() const
Returns the message content.
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:891
Bulds gum::prm:PRMInterface from gum::prm::o3prm::O3Interface.
std::string & label()
Definition O3prm.cpp:286
O3Position & position()
Definition O3prm.cpp:282
Resolves names for the different O3PRM factories.
The O3PRM is part of the AST of the O3PRM language.
Definition O3prm.h:915
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...
void setClassPath(std::string_view class_path)
This methods defines the list of paths to look for o3prm files.
void _parseStream_(std::istream &input, const std::string &filename, const std::string &module)
Idx errLine(Idx i) const
line of ith error or warning
Size readString(const std::string &string)
With readString method, you must set the current path to search from import yourself,...
std::wstring errFilename(Idx i) const
filename of ith error or warning
gum::prm::PRM< GUM_SCALAR > * prm()
void parseStream(std::istream &input, std::ostream &output, std::string module="")
Size errors() const
publishing Errors API
O3prmReader & operator=(const O3prmReader &src)
void showErrorCounts(std::ostream &o=std::cerr) const
send on std::cerr the number of errors and the number of warnings
void showElegantErrors(std::ostream &o=std::cerr) const
send on std::cerr the list of errors
const ErrorsContainer & errorsContainer() const
publishing Errors API
bool errIsError(Idx i) const
type of ith error or warning
std::string _clean_(std::string text) const
void _readStream_(std::istream &input, const std::string &file, std::string module="")
Size readFile(std::string_view file, std::string_view module="")
Read file and load its content using a PRMFactory. The package parameter set the file's content packa...
Idx errCol(Idx i) const
col of ith error or warning
std::vector< const O3Import * > _copyImports_()
std::string _print_(const ParseError &err) const
std::unique_ptr< O3PRM > _o3_prm_
void _parseImport_(const O3Import &i, const std::string &module_path)
std::string errMsg(Idx i) const
message of ith error or warning
void showElegantErrorsAndWarnings(std::ostream &o=std::cerr) const
send on std::cerr the list of errors or warnings
PRM< GUM_SCALAR > * _prm_
std::vector< std::string > _class_path_
void addClassPath(std::string_view class_path)
Add a list of paths to look for o3prm files.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
#define GUM_SHOWERROR(e)
Definition exceptions.h:89
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(std::string_view s, std::string_view val, std::string_view new_val)
Replace val by new_val in s.
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.