Skip to content

Commit

Permalink
Add GCode parsing functionality
Browse files Browse the repository at this point in the history
Added multiple headers to include/dulcificum/gcode/ast for AST handling using variants and templates. Also added function to parse gcode into AST. These changes allow transforming gcode to AST which can be used for further analysis or translation to other formats. Added example usage to the main translator application.

Contribute to CURA-10561
  • Loading branch information
jellespijker committed Oct 16, 2023
1 parent 0a546e7 commit 4a338f1
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 3 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ add_library(dulcificum ${DULCIFICUM_SRC})
target_link_libraries(dulcificum
PUBLIC
nlohmann_json::nlohmann_json
ctre::ctre
PRIVATE
range-v3::range-v3
ctre::ctre
spdlog::spdlog)

target_include_directories(dulcificum
Expand Down
33 changes: 31 additions & 2 deletions apps/translator_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,29 @@
#include <spdlog/spdlog.h>

#include <docopt/docopt.h>
#include <dulcificum/gcode/parse.h>
#include <dulcificum/utils/io.h>
#include <map>

template<typename... Ts>
struct Overload : Ts...
{
using Ts::operator()...;
};
template<class... Ts>
Overload(Ts...) -> Overload<Ts...>;

int main(int argc, const char** argv)
{
constexpr bool show_help = true;
const std::map<std::string, docopt::value> args
= docopt::docopt(fmt::format(apps::cmdline::USAGE, apps::cmdline::NAME), { argv + 1, argv + argc }, show_help, apps::cmdline::VERSION_ID);

if (args.contains("--quiet"))
if (args.at("--quiet").asBool())
{
spdlog::set_level(spdlog::level::err);
}
else if (args.contains("--verbose"))
else if (args.at("--verbose").asBool())
{
spdlog::set_level(spdlog::level::debug);
}
Expand All @@ -24,4 +34,23 @@ int main(int argc, const char** argv)
spdlog::set_level(spdlog::level::info);
}
spdlog::info("Tasting the menu");

auto input{ dulcificum::utils::readFile(args.at("INPUT").asString()).value() };
auto ast = dulcificum::gcode::parse(input);

auto TypeOfNode = Overload{ [](dulcificum::gcode::ast::G1)
{
spdlog::info("G1");
},
[](auto)
{
spdlog::info("Not yet implemented");
} };

for (auto& node : ast)
{
std::visit(TypeOfNode, node);
}

auto x = 1;
}
38 changes: 38 additions & 0 deletions include/dulcificum/gcode/ast/ast.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_AST_H
#define DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_AST_H

#include "dulcificum/gcode/ast/g0.h"
#include "dulcificum/gcode/ast/g1.h"

#include <variant>
#include <vector>
#include <string_view>

namespace dulcificum::gcode::ast
{

using Unknown = Entry<R"((.*))">;
using Comment = Entry<R"(;(.*))">;
using node_t = std::variant<Unknown, Comment, G0, G1>;
using ast_t = std::vector<node_t>;

node_t factory(size_t index, std::string line)
{
if (line.starts_with(';'))
{
return Comment { index, line };
}
if (line.starts_with("G0"))
{
return G0 { index, line };
}
if (line.starts_with("G1"))
{
return G1 { index, line };
}
return Unknown { index, line };
}

} // namespace dulcificum::gcode::ast

#endif // DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_AST_H
33 changes: 33 additions & 0 deletions include/dulcificum/gcode/ast/entry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_ENTRY_H
#define DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_ENTRY_H

#include "dulcificum/utils/char_range_literal.h"

#include <cstddef>
#include <ctre.hpp>
#include <string>

namespace dulcificum::gcode::ast
{

template<dulcificum::utils::CharRangeLiteral Pattern>
class Entry
{
public:
Entry() = delete;
Entry(size_t index, std::string line)
: index{ index }
, line{ std::move(line) } {};

size_t index;
std::string line;

constexpr auto get()
{
return ctre::match<Pattern.value>(line);
}
};

} // namespace dulcificum::gcode::ast

#endif // DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_ENTRY_H
17 changes: 17 additions & 0 deletions include/dulcificum/gcode/ast/g0.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_G0_H
#define DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_G0_H

#include "dulcificum/gcode/ast/entry.h"

namespace dulcificum::gcode::ast
{
class G0 : public Entry<R"(G0((?:\sX(?<X>\d+(?:\.\d+)?))|(?:\sY(?<Y>\d+(?:\.\d+)?))|(?:\sZ(?<Z>\d+(?:\.\d+)?))|(?:\sE(?<E>\d+(?:\.\d+)?))|(?:\sF(?<F>\d+(?:\.\d+)?)))*$)">
{
public:
G0() = delete;
G0(size_t index, std::string line)
: Entry{ index, std::move(line) } {};
};
} // namespace dulcificum::gcode::ast

#endif // DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_G0_H
17 changes: 17 additions & 0 deletions include/dulcificum/gcode/ast/g1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_G1_H
#define DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_G1_H

#include "dulcificum/gcode/ast/entry.h"

namespace dulcificum::gcode::ast
{
class G1 : public Entry<R"(G1((?:\sX(?<X>\d+(?:\.\d+)?))|(?:\sY(?<Y>\d+(?:\.\d+)?))|(?:\sZ(?<Z>\d+(?:\.\d+)?))|(?:\sE(?<E>\d+(?:\.\d+)?))|(?:\sF(?<F>\d+(?:\.\d+)?)))*$)">
{
public:
G1() = delete;
G1(size_t index, std::string line)
: Entry{ index, std::move(line) } {};
};
} // namespace dulcificum::gcode::ast

#endif // DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_AST_G1_H
34 changes: 34 additions & 0 deletions include/dulcificum/gcode/parse.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_PARSE_H
#define DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_PARSE_H

#include "dulcificum/gcode/ast/ast.h"

#include <spdlog/spdlog.h>

#include <cstddef>
#include <sstream>
#include <string>
#include <string_view>

namespace dulcificum::gcode
{

ast::ast_t parse(std::string_view content)
{
std::istringstream stream(content.data());
std::string line;
ast::ast_t ast;

size_t index{ 0 };
while (std::getline(stream, line))
{
ast.emplace_back(ast::factory(index++, line));
}

return ast;
}


} // namespace dulcificum::gcode

#endif // DULCIFICUM_INCLUDE_DULCIFICUM_GCODE_PARSE_H
24 changes: 24 additions & 0 deletions include/dulcificum/utils/char_range_literal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef DULCIFICUM_INCLUDE_DULCIFICUM_UTILS_CHAR_RANGE_LITERAL_H
#define DULCIFICUM_INCLUDE_DULCIFICUM_UTILS_CHAR_RANGE_LITERAL_H

#include <algorithm>
#include <cstddef>

namespace dulcificum::utils
{

// NOLINTBEGIN
template<std::size_t N>
struct CharRangeLiteral
{
constexpr CharRangeLiteral(const char (&str)[N]) noexcept
{
std::copy_n(str, N, value);
}
char value[N]; ///< The character array holding the literal
};
// NOLINTEND

} // namespace dulcificum::utils

#endif // DULCIFICUM_INCLUDE_DULCIFICUM_UTILS_CHAR_RANGE_LITERAL_H

0 comments on commit 4a338f1

Please sign in to comment.