From 8d36970851a1ad9d3cbe1b081ca856b81fc4680f Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Tue, 17 Oct 2023 17:56:45 +0200 Subject: [PATCH] improve Gcode parsing A StringViewToDouble conversion function is added. With help of this function, improved the Gcode parsing to extract more data for each Gcode command. Now it correctly identifies and extracts all relevant command data for each command line, including optional parameters, and stores them in corresponding classes' member variables. More specifically, the changes were made in classes representing G0, G1, m104, and other Gcode commands. Additionally, for each updated class a std::optional field was added for each optional command parameter which can appear in actual Gcode command, allowing to check if certain parameter was set in the given Gcode command. Contribute to CURA-10561 --- CMakeLists.txt | 1 + include/dulcificum/gcode/ast/acceleration.h | 19 +- .../dulcificum/gcode/ast/bed_temperature.h | 11 +- .../dulcificum/gcode/ast/comment_commands.h | 29 +- include/dulcificum/gcode/ast/entry.h | 21 +- .../gcode/ast/extruder_temperature.h | 17 +- include/dulcificum/gcode/ast/fan.h | 6 +- include/dulcificum/gcode/ast/position.h | 11 +- include/dulcificum/gcode/ast/purge.h | 6 +- include/dulcificum/gcode/ast/toolchange.h | 6 +- include/dulcificum/gcode/ast/translate.h | 28 +- include/dulcificum/utils/svtod.h | 13 + src/gcode/ast/operators.cpp | 273 +++++++++++++++++- src/proto_path/translate.cpp | 23 +- src/utils/svtod.cpp | 13 + 15 files changed, 410 insertions(+), 67 deletions(-) create mode 100644 include/dulcificum/utils/svtod.h create mode 100644 src/utils/svtod.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c40401..bfe9bd0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ set(DULCIFICUM_SRC src/proto_path/translate.cpp src/utils/io.cpp + src/utils/svtod.cpp src/command_types.cpp ) add_library(dulcificum ${DULCIFICUM_SRC}) diff --git a/include/dulcificum/gcode/ast/acceleration.h b/include/dulcificum/gcode/ast/acceleration.h index 029f890..043728d 100644 --- a/include/dulcificum/gcode/ast/acceleration.h +++ b/include/dulcificum/gcode/ast/acceleration.h @@ -3,6 +3,8 @@ #include "dulcificum/gcode/ast/entry.h" +#include + namespace dulcificum::gcode::ast { /*! @@ -10,12 +12,14 @@ namespace dulcificum::gcode::ast * P = Printing acceleration. Used for moves that include extrusion * T = Travel acceleration. Used for moves that include no extrusion */ -class M204 : public Entry\d+(?:\.\d+)?))|(?:\sT(?\d+(?:\.\d+)?)))*$)"> +class M204 : public Entry\d+(?:\.\d+)?))|(?:\sT(?\d+(?:\.\d+)?))|(?:\sS(?\d+(?:\.\d+)?)))*$)"> { public: M204() = delete; - M204(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + M204(size_t index, std::string line); + std::optional P; + std::optional T; + std::optional S; }; /*! @@ -25,12 +29,15 @@ class M204 : public Entry\d+(?:\.\d+)?))|(?:\sT(?\d+(?:\. * Z = Z max jerk (units/s) * E = E max jerk (units/s) */ -class M205 : public Entry\d+(?:\.\d+)?))|(?:\sY(?\d+(?:\.\d+)?))|(?:\sZ(?\d+(?:\.\d+)?))|(?:\sE(?\d+(?:\.\d+)?)))*$)"> +class M205 : public Entry-?\d+(?:\.\d+)?))|(?:\sY(?-?\d+(?:\.\d+)?))|(?:\sZ(?-?\d+(?:\.\d+)?))|(?:\sE(?-?\d+(?:\.\d+)?)))*$)"> { public: M205() = delete; - M205(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + M205(size_t index, std::string line); + std::optional X; + std::optional Y; + std::optional Z; + std::optional E; }; } // namespace dulcificum::gcode::ast diff --git a/include/dulcificum/gcode/ast/bed_temperature.h b/include/dulcificum/gcode/ast/bed_temperature.h index 2f66370..bb365aa 100644 --- a/include/dulcificum/gcode/ast/bed_temperature.h +++ b/include/dulcificum/gcode/ast/bed_temperature.h @@ -3,6 +3,8 @@ #include "dulcificum/gcode/ast/entry.h" +#include + namespace dulcificum::gcode::ast { /*! @@ -13,8 +15,8 @@ class M140 : public Entry\d+(?:\.\d+)?)))*$)"> { public: M140() = delete; - M140(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + M140(size_t index, std::string line); + std::optional S; }; /*! @@ -26,8 +28,9 @@ class M190 : public Entry\d+(?:\.\d+)?))|(?:\sR(?\d+(?:\. { public: M190() = delete; - M190(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + M190(size_t index, std::string line); + std::optional S; + std::optional R; }; } // namespace dulcificum::gcode::ast diff --git a/include/dulcificum/gcode/ast/comment_commands.h b/include/dulcificum/gcode/ast/comment_commands.h index 37bebfd..34a00ea 100644 --- a/include/dulcificum/gcode/ast/comment_commands.h +++ b/include/dulcificum/gcode/ast/comment_commands.h @@ -3,18 +3,20 @@ #include "dulcificum/gcode/ast/entry.h" +#include + namespace dulcificum::gcode::ast { /*! * /brief The layer index * L = index */ -class Layer : public Entry\d*))"> +class Layer : public Entry-?\d+))"> { public: Layer() = delete; - Layer(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + Layer(size_t index, std::string line); + std::optional L; }; /*! @@ -25,8 +27,8 @@ class Mesh : public Entry.*))"> { public: Mesh() = delete; - Mesh(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + Mesh(size_t index, std::string line); + std::optional M; }; /*! @@ -37,8 +39,8 @@ class FeatureType : public Entry.*))"> { public: FeatureType() = delete; - FeatureType(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + FeatureType(size_t index, std::string line); + std::optional T; }; /*! @@ -50,8 +52,9 @@ class InitialTemperatureExtruder : public Entry\d)\.IN { public: InitialTemperatureExtruder() = delete; - InitialTemperatureExtruder(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + InitialTemperatureExtruder(size_t index, std::string line); + std::optional T; + std::optional S; }; /*! @@ -62,8 +65,8 @@ class InitialTemperatureBuildPlate : public Entry S; }; /*! @@ -74,8 +77,8 @@ class BuildVolumeTemperature : public Entry([ { public: BuildVolumeTemperature() = delete; - BuildVolumeTemperature(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + BuildVolumeTemperature(size_t index, std::string line); + std::optional S; }; } // namespace dulcificum::gcode::ast diff --git a/include/dulcificum/gcode/ast/entry.h b/include/dulcificum/gcode/ast/entry.h index 3534ed5..4bb724b 100644 --- a/include/dulcificum/gcode/ast/entry.h +++ b/include/dulcificum/gcode/ast/entry.h @@ -3,19 +3,27 @@ #include "dulcificum/utils/char_range_literal.h" -#include - +#include #include +#include #include +#include #include +#include +#include +#include +#include +#include namespace dulcificum::gcode::ast { -template +template class Entry { public: + using value_type = std::map>; + Entry() = delete; Entry(size_t index, std::string line) : index{ index } @@ -23,15 +31,16 @@ class Entry size_t index; std::string line; + static inline constexpr ctll::fixed_string pattern{ Pattern.value }; constexpr auto get() { - return ctre::match(line); + return ctre::match(line); }; - virtual constexpr void operator()() + virtual value_type operator()() { - spdlog::info("lino: {} -> {}", index, line); + return {}; }; }; diff --git a/include/dulcificum/gcode/ast/extruder_temperature.h b/include/dulcificum/gcode/ast/extruder_temperature.h index eb995de..2a1ddc3 100644 --- a/include/dulcificum/gcode/ast/extruder_temperature.h +++ b/include/dulcificum/gcode/ast/extruder_temperature.h @@ -3,18 +3,21 @@ #include "dulcificum/gcode/ast/entry.h" +#include + namespace dulcificum::gcode::ast { /*! * /brief Set a new target hot end temperature (non-blocking). * S = Target temperature */ -class M104 : public Entry\d+(?:\.\d+)?)))*$)"> +class M104 : public Entry\d+(?:\.\d+)?))|(?:\sT(?\d+(?:\.\d+)?)))*$)"> { public: M104() = delete; - M104(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + M104(size_t index, std::string line); + std::optional S; + std::optional T; }; /*! @@ -22,12 +25,14 @@ class M104 : public Entry\d+(?:\.\d+)?)))*$)"> * R = Target temperature (wait for cooling or heating). * S = Target temperature (wait only when heating) */ -class M109 : public Entry\d+(?:\.\d+)?))|(?:\sR(?\d+(?:\.\d+)?)))*$)"> +class M109 : public Entry\d+(?:\.\d+)?))|(?:\sR(?\d+(?:\.\d+)?))|(?:\sT(?\d+(?:\.\d+)?)))*$)"> { public: M109() = delete; - M109(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + M109(size_t index, std::string line); + std::optional S; + std::optional R; + std::optional T; }; } // namespace dulcificum::gcode::ast diff --git a/include/dulcificum/gcode/ast/fan.h b/include/dulcificum/gcode/ast/fan.h index bf8d43b..25e650a 100644 --- a/include/dulcificum/gcode/ast/fan.h +++ b/include/dulcificum/gcode/ast/fan.h @@ -3,6 +3,8 @@ #include "dulcificum/gcode/ast/entry.h" +#include + namespace dulcificum::gcode::ast { /*! @@ -13,8 +15,8 @@ class M106 : public Entry\d+(?:\.\d+)?)))*$)"> { public: M106() = delete; - M106(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + M106(size_t index, std::string line); + std::optional S; }; /*! diff --git a/include/dulcificum/gcode/ast/position.h b/include/dulcificum/gcode/ast/position.h index 785ec28..efacaf3 100644 --- a/include/dulcificum/gcode/ast/position.h +++ b/include/dulcificum/gcode/ast/position.h @@ -3,6 +3,8 @@ #include "dulcificum/gcode/ast/entry.h" +#include + namespace dulcificum::gcode::ast { /*! @@ -12,12 +14,15 @@ namespace dulcificum::gcode::ast * Z = New Z axis position * E New extruder position */ -class G92 : public Entry\d+(?:\.\d+)?))|(?:\sY(?\d+(?:\.\d+)?))|(?:\sZ(?\d+(?:\.\d+)?))|(?:\sE(?\d+(?:\.\d+)?)))*$)"> +class G92 : public Entry-?\d+(?:\.\d+)?))|(?:\sY(?-?\d+(?:\.\d+)?))|(?:\sZ(?-?\d+(?:\.\d+)?))|(?:\sE(?-?\d+(?:\.\d+)?)))*$)"> { public: G92() = delete; - G92(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + G92(size_t index, std::string line); + std::optional X; + std::optional Y; + std::optional Z; + std::optional E; }; } // namespace dulcificum::gcode::ast diff --git a/include/dulcificum/gcode/ast/purge.h b/include/dulcificum/gcode/ast/purge.h index 854d06a..49c83dc 100644 --- a/include/dulcificum/gcode/ast/purge.h +++ b/include/dulcificum/gcode/ast/purge.h @@ -3,6 +3,8 @@ #include "dulcificum/gcode/ast/entry.h" +#include + namespace dulcificum::gcode::ast { /*! @@ -12,8 +14,8 @@ class G280 : public Entry\d+(?:\.\d+)?)))*$)"> { public: G280() = delete; - G280(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + G280(size_t index, std::string line); + std::optional S; }; } // namespace dulcificum::gcode::ast diff --git a/include/dulcificum/gcode/ast/toolchange.h b/include/dulcificum/gcode/ast/toolchange.h index 7a150c1..72a542a 100644 --- a/include/dulcificum/gcode/ast/toolchange.h +++ b/include/dulcificum/gcode/ast/toolchange.h @@ -8,12 +8,12 @@ namespace dulcificum::gcode::ast /*! * /brief Switch to the specified tool */ -class T : public Entry\d))"> +class T : public Entry\d))"> { public: T() = delete; - T(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; + T(size_t index, std::string line); + std::optional S; }; } // namespace dulcificum::gcode::ast diff --git a/include/dulcificum/gcode/ast/translate.h b/include/dulcificum/gcode/ast/translate.h index d030284..225186d 100644 --- a/include/dulcificum/gcode/ast/translate.h +++ b/include/dulcificum/gcode/ast/translate.h @@ -3,6 +3,10 @@ #include "dulcificum/gcode/ast/entry.h" +#include +#include +#include + namespace dulcificum::gcode::ast { @@ -14,14 +18,16 @@ namespace dulcificum::gcode::ast * E = An absolute or relative coordinate on the E axis (in current units). * F = The maximum movement rate of the move between the start and end point. */ -class G0 : public Entry\d+(?:\.\d+)?))|(?:\sY(?\d+(?:\.\d+)?))|(?:\sZ(?\d+(?:\.\d+)?))|(?:\sE(?\d+(?:\.\d+)?))|(?:\sF(?\d+(?:\.\d+)?)))*$)"> +class G0 : public Entry-?\d+(?:\.\d+)?))|(?:\sY(?-?\d+(?:\.\d+)?))|(?:\sZ(?-?\d+(?:\.\d+)?))|(?:\sE(?-?\d+(?:\.\d+)?))|(?:\sF(?-?\d+(?:\.\d+)?)))*$)"> { public: G0() = delete; - G0(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; - - void operator()() override final; + G0(size_t index, std::string line); + std::optional X; + std::optional Y; + std::optional Z; + std::optional E; + std::optional F; }; /*! @@ -32,14 +38,16 @@ class G0 : public Entry\d+(?:\.\d+)?))|(?:\sY(?\d+(?:\.\d+) * E = An absolute or relative coordinate on the E axis (in current units). * F = The maximum movement rate of the move between the start and end point. */ -class G1 : public Entry\d+(?:\.\d+)?))|(?:\sY(?\d+(?:\.\d+)?))|(?:\sZ(?\d+(?:\.\d+)?))|(?:\sE(?\d+(?:\.\d+)?))|(?:\sF(?\d+(?:\.\d+)?)))*$)"> +class G1 : public Entry-?\d+(?:\.\d+)?))|(?:\sY(?-?\d+(?:\.\d+)?))|(?:\sZ(?-?\d+(?:\.\d+)?))|(?:\sE(?-?\d+(?:\.\d+)?))|(?:\sF(?-?\d+(?:\.\d+)?)))*$)"> { public: G1() = delete; - G1(size_t index, std::string line) - : Entry{ index, std::move(line) } {}; - - void operator()() override final; + G1(size_t index, std::string line); + std::optional X; + std::optional Y; + std::optional Z; + std::optional E; + std::optional F; }; } // namespace dulcificum::gcode::ast diff --git a/include/dulcificum/utils/svtod.h b/include/dulcificum/utils/svtod.h new file mode 100644 index 0000000..919a776 --- /dev/null +++ b/include/dulcificum/utils/svtod.h @@ -0,0 +1,13 @@ +#ifndef INCLUDE_DULCIFICUM_UTILS_SVTOD_H +#define INCLUDE_DULCIFICUM_UTILS_SVTOD_H + +#include + +namespace dulcificum::utils +{ + +double StringViewToDouble(std::string_view sv); + +} // namespace dulcificum::utils + +#endif // INCLUDE_DULCIFICUM_UTILS_SVTOD_H diff --git a/src/gcode/ast/operators.cpp b/src/gcode/ast/operators.cpp index 696402f..71e3be9 100644 --- a/src/gcode/ast/operators.cpp +++ b/src/gcode/ast/operators.cpp @@ -1,27 +1,280 @@ +#include "dulcificum/gcode/ast/acceleration.h" +#include "dulcificum/gcode/ast/bed_temperature.h" +#include "dulcificum/gcode/ast/comment_commands.h" +#include "dulcificum/gcode/ast/extruder_temperature.h" +#include "dulcificum/gcode/ast/fan.h" +#include "dulcificum/gcode/ast/position.h" +#include "dulcificum/gcode/ast/purge.h" +#include "dulcificum/gcode/ast/toolchange.h" #include "dulcificum/gcode/ast/translate.h" +#include "dulcificum/utils/svtod.h" -#include - +#include namespace dulcificum::gcode::ast { +BuildVolumeTemperature::BuildVolumeTemperature(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"S">()) + { + S = utils::StringViewToDouble(value.to_view()); + } + else + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +FeatureType::FeatureType(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"T">()) + { + T = value.to_view(); + } + else + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +G0::G0(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"X">()) { X = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"Y">()) { Y = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"Z">()) { Z = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"E">()) { E = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"F">()) { F = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (X == std::nullopt && Y == std::nullopt && Z == std::nullopt && E == std::nullopt && F == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +G1::G1(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"X">()) { X = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"Y">()) { Y = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"Z">()) { Z = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"E">()) { E = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"F">()) { F = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (X == std::nullopt && Y == std::nullopt && Z == std::nullopt && E == std::nullopt && F == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +G280::G280(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"S">()) + { + S = utils::StringViewToDouble(value.to_view()); + } + else + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +G92::G92(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"X">()) { X = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"Y">()) { Y = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"Z">()) { Z = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"E">()) { E = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (X == std::nullopt && Y == std::nullopt && Z == std::nullopt && E == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +InitialTemperatureBuildPlate::InitialTemperatureBuildPlate(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"S">()) + { + S = utils::StringViewToDouble(value.to_view()); + } + else + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +InitialTemperatureExtruder::InitialTemperatureExtruder(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"T">()) { T = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"S">()) { S = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (T == std::nullopt && S == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +Layer::Layer(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"L">()) + { + L = utils::StringViewToDouble(value.to_view()); + } + else + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} -void G0::operator()() +M104::M104(size_t index, std::string line) + : Entry{ index, std::move(line) } { - if (auto x = get().get<"X">()) + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"S">()) { S = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"T">()) { T = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (S == std::nullopt && T == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +M106::M106(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"S">()) + { + S = utils::StringViewToDouble(value.to_view()); + } + else + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +M109::M109(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"S">()) { S = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"R">()) { R = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"T">()) { T = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (S == std::nullopt && R == std::nullopt && T == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +M140::M140(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"S">()) + { + S = utils::StringViewToDouble(value.to_view()); + } + else { - spdlog::debug("x: {}", x); + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); } - spdlog::info("lino: {} -> {}", index, line); } -void G1::operator()() +M190::M190(size_t index, std::string line) + : Entry{ index, std::move(line) } { - if (auto x = get().get<"Y">()) + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"S">()) { S = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"R">()) { R = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (S == std::nullopt && R == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +M204::M204(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"P">()) { P = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"T">()) { T = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"S">()) { S = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (P == std::nullopt && T == std::nullopt && S == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +M205::M205(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + // clang-format off + if (const auto& value = matches.get<"X">()) { X = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"Y">()) { Y = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"Z">()) { Z = utils::StringViewToDouble(value.to_view()); } + if (const auto& value = matches.get<"E">()) { E = utils::StringViewToDouble(value.to_view()); } + // clang-format on + if (X == std::nullopt && Y == std::nullopt && Z == std::nullopt && E == std::nullopt) + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +Mesh::Mesh(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"M">()) + { + M = value.to_view(); + } + else + { + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); + } +} + +T::T(size_t index, std::string line) + : Entry{ index, std::move(line) } +{ + const auto& matches = get(); + if (const auto& value = matches.get<"S">()) + { + S = utils::StringViewToDouble(value.to_view()); + } + else { - spdlog::debug("Y: {}", x); + throw std::runtime_error(fmt::format("Unable to parse lino: {}", index)); } - spdlog::info("lino: {} -> {}", index, line); } } // namespace dulcificum::gcode::ast \ No newline at end of file diff --git a/src/proto_path/translate.cpp b/src/proto_path/translate.cpp index f20130e..ee59a30 100644 --- a/src/proto_path/translate.cpp +++ b/src/proto_path/translate.cpp @@ -1,14 +1,33 @@ #include "dulcificum/proto_path/translate.h" +#include "dulcificum/gcode/ast/ast.h" +#include "dulcificum/proto_path/ast/ast.h" + #include +#include + namespace dulcificum::proto_path { -ast::ast_t translate(gcode::ast::ast_t gcode) +proto_path::ast::ast_t translate(gcode::ast::ast_t gcode) { spdlog::info("Translating GCode to Proto Path"); - ast::ast_t ast; + proto_path::ast::ast_t ast; + + for (auto& node : gcode) + { + std::visit( + [](auto& n) + { + auto args = n(); + if (args.contains("X")) + { + spdlog::info("X: {}", std::get(args["X"])); + } + }, + node); + } return ast; } diff --git a/src/utils/svtod.cpp b/src/utils/svtod.cpp new file mode 100644 index 0000000..a249ca9 --- /dev/null +++ b/src/utils/svtod.cpp @@ -0,0 +1,13 @@ +#include "dulcificum/utils/svtod.h" + +#include + +namespace dulcificum::utils +{ +double StringViewToDouble(std::string_view sv) +{ + double value = 0.0; + std::from_chars(sv.data(), sv.data() + sv.size(), value); + return value; +} +} // namespace dulcificum::utils \ No newline at end of file