15 #ifndef OPENSCENARIO_INTERPRETER__READER__ATTRIBUTE_HPP_
16 #define OPENSCENARIO_INTERPRETER__READER__ATTRIBUTE_HPP_
18 #include <ament_index_cpp/get_package_share_directory.hpp>
19 #include <boost/algorithm/string/replace.hpp>
26 #include <pugixml.hpp>
30 #include <unordered_map>
34 inline namespace reader
36 template <
typename Scope>
39 auto dirname = [](
auto &&,
auto && scope) {
return scope.
dirname(); };
41 auto find_pkg_share = [](
auto && package_name,
auto &&) {
42 return ament_index_cpp::get_package_share_directory(package_name);
45 auto ros2 = [](
auto && arguments,
auto &&) {
46 auto remove_trailing_newline = [](
auto && s) {
47 while (s.back() ==
'\n') {
52 if (
auto && result = remove_trailing_newline(
concealer::dollar(
"ros2 " + arguments));
53 result.find(
'\n') != std::string::npos) {
55 "The substitution result by `$(ros2 ...)` must not contain a newline character. "
57 arguments,
")` and the result was ",
58 std::quoted(boost::replace_all_copy(result,
"\n",
"\\n")),
59 ", which is unacceptable for the reasons stated above.");
65 auto var = [](
auto && name,
auto && scope) {
67 if (
const auto found = scope.
ref(name); found) {
68 return boost::lexical_cast<String>(found);
75 static const std::unordered_map<
84 {
"find-pkg-share", find_pkg_share},
90 static const auto pattern = std::regex(R
"((.*)\$\((([\w-]+)\s?([^\)]*))\)(.*))");
92 for (std::smatch result; std::regex_match(attribute, result, pattern);) {
93 if (
const auto iter = substitutions.find(result.str(3)); iter != std::end(substitutions)) {
94 attribute = result.str(1) + std::get<1>(*iter)(result.str(4), scope) + result.str(5);
96 throw SyntaxError(
"Unknown substitution ", std::quoted(result.str(3)),
" specified");
103 template <
typename T,
typename Node,
typename Scope>
106 auto is_openscenario_standard_expression = [](
const auto & s) {
107 return s.substr(0, 2) ==
"${" and s.back() ==
'}';
110 auto read_openscenario_standard_expression = [&](
const auto & s) {
111 return boost::lexical_cast<T>(
evaluate(
std::string(std::begin(s) + 2, std::end(s) - 1), scope));
114 auto is_openscenario_standard_parameter_reference = [](
const auto & s) {
115 return s.front() ==
'$';
118 auto read_openscenario_standard_parameter_reference = [&](
const auto & s) {
120 if (
auto &&
object = scope.ref(s.substr(1)); object) {
121 return boost::lexical_cast<T>(boost::lexical_cast<String>(
object));
124 "There is no parameter named ", std::quoted(s.substr(1)),
" (Attribute ", std::quoted(name),
125 " of class ", std::quoted(node.name()),
" references this parameter)");
129 auto read_openscenario_standard_literal = [&](
const auto & s) {
131 return boost::lexical_cast<T>(s);
132 }
catch (
const boost::bad_lexical_cast &) {
134 "Value ", std::quoted(s),
" specified for attribute ", std::quoted(name),
135 " is invalid (Is not value of type ",
makeTypename(
typeid(T)),
")");
141 if (
const auto & attribute = node.attribute(name.c_str())) {
145 }
else if (is_openscenario_standard_expression(value)) {
146 return read_openscenario_standard_expression(value);
147 }
else if (is_openscenario_standard_parameter_reference(value)) {
148 return read_openscenario_standard_parameter_reference(value);
150 return read_openscenario_standard_literal(value);
154 "Required attribute ", std::quoted(name),
" not specified for class ",
155 std::quoted(node.name()));
159 template <
typename T,
typename Node,
typename Scope>
162 if (node.attribute(name.c_str())) {
163 return readAttribute<T>(name, node, scope);
169 template <
typename T,
typename Node,
typename Scope>
172 if (node.attribute(name.c_str())) {
173 return std::make_optional(readAttribute<T>(name, node, scope));
175 return std::optional<T>();
Definition: scope.hpp:154
auto dirname() const -> std::string
Definition: scope.cpp:107
auto ref(Ts &&... xs) const -> decltype(auto)
Definition: scope.hpp:210
auto dollar(const std::string &command) -> std::string
Definition: execute.cpp:57
auto substitute(std::string attribute, Scope &scope)
Definition: attribute.hpp:37
auto readAttribute(const std::string &name, const Node &node, const Scope &scope) -> T
Definition: attribute.hpp:104
std::string evaluate(const std::string &, const Scope &)
Definition: evaluate.cpp:237
std::string String
Definition: string.hpp:24
auto makeTypename(Ts &&... xs)
Definition: demangle.hpp:30
std::string string
Definition: junit5.hpp:26