diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..f0247f1f --- /dev/null +++ b/.clang-format @@ -0,0 +1,39 @@ +Language: Cpp +BasedOnStyle: LLVM +IndentWidth: 4 +IndentExternBlock: Indent +ColumnLimit: 100 +NamespaceIndentation: All +PointerAlignment: Left +ReferenceAlignment: Left +PackConstructorInitializers: Never +AlignConsecutiveDeclarations: AcrossComments +AlignConsecutiveAssignments: AcrossComments +AlignConsecutiveBitFields: AcrossComments +AlignTrailingComments: true +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AlwaysBreakTemplateDeclarations: Yes +IndentPPDirectives: BeforeHash +PPIndentWidth: 4 +AlignAfterOpenBracket: BlockIndent +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +BinPackParameters: false +BinPackArguments: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: Always +AlignEscapedNewlines: Left +AlignOperands: AlignAfterOperator +AllowShortEnumsOnASingleLine: false +AllowShortLambdasOnASingleLine: Empty +BreakBeforeBraces: Attach +BreakConstructorInitializers: AfterColon +BreakStringLiterals: true +MaxEmptyLinesToKeep: 1 +QualifierAlignment: Left +SeparateDefinitionBlocks: Always +UseTab: Never +IndentCaseLabels: true diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..c613edce --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.21) +project(MyProject) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +add_executable(MyExecutable main.cpp) diff --git a/main.cpp b/main.cpp new file mode 100644 index 00000000..1221d9e8 --- /dev/null +++ b/main.cpp @@ -0,0 +1,813 @@ +#include +#include +#include +#include +#include +#include + +#define DEBUG 1 + +#ifdef DEBUG + #define LOG_DEBUG(...) printf(__VA_ARGS__); +#elif + #define LOG_DEBUG(...) +#endif + +#ifdef _WIN32 + #include + +struct FileMapping { + HANDLE hFile; + HANDLE hMapFile; + LPVOID lpBase; + LARGE_INTEGER size; + bool is_ok = false; + + FileMapping(const char* filename) { + hFile = CreateFile( + filename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { + std::cerr << "Could not open file." << std::endl; + return; + } + + if (!GetFileSizeEx(hFile, &size)) { + std::cerr << "Could not get file size." << std::endl; + CloseHandle(hFile); + return; + } + + hMapFile = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + + if (hMapFile == NULL) { + std::cerr << "Could not create file mapping object." << std::endl; + CloseHandle(hFile); + return; + } + + lpBase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); + + if (lpBase == NULL) { + std::cerr << "Could not map view of file." << std::endl; + CloseHandle(hMapFile); + CloseHandle(hFile); + return; + } + + is_ok = true; + } + + ~FileMapping() { + UnmapViewOfFile(this->lpBase); + CloseHandle(this->hMapFile); + CloseHandle(this->hFile); + } + + void* GetMapping() { + return lpBase; + } + + uint64_t GetSize() { + return this->size.QuadPart; + } +}; + +#elif __unix__ + + #include + #include + #include + #include + +class FileMapping { + int fd; + void* map; + size_t size; + bool is_ok = false; + + FileMapping(const char* filename) { + fd = open(filename, O_RDONLY); + if (fd == -1) { + std::cerr << "Could not open file." << std::endl; + return; + } + + struct stat st; + if (fstat(fd, &st) == -1) { + std::cerr << "Could not get file size." << std::endl; + close(fd); + return; + } + + size = st.st_size; + map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); + + if (map == MAP_FAILED) { + std::cerr << "Could not map file." << std::endl; + close(fd); + return; + } + + is_ok = true; + } + + ~FileMapping() { + munmap(map, size); + close(fd); + } + + void* GetMapping() { + return lpBase; + } + + uint64_t GetSize() { + return this->size; + } +} + +#endif + +enum class TokenType { + UNKNOWN = 0, + INVALID = 1, + INTEGER = 2, + STRING = 3, + G01_COMMAND = 4, + G02_COMMAND = 5, + G03_COMMAND = 6, + G04_COMMAND = 7, + G36_COMMAND = 8, + G37_COMMAND = 9, + G54_COMMAND = 10, + G55_COMMAND = 11, + G70_COMMAND = 12, + G71_COMMAND = 13, + G74_COMMAND = 14, + G75_COMMAND = 15, + G90_COMMAND = 16, + G91_COMMAND = 17, + D01_COMMAND = 18, + D02_COMMAND = 19, + D03_COMMAND = 20, + DNN_SELECT = 21, + COORDINATE_COMMAND = 23, + FS_EXTENDED_COMMAND = 24, + FS_ZERO_OMISSION = 26, + FS_COORDINATE_TYPE = 25, + FS_AXIS_FORMAT = 27, + MODE_EXTENDED_COMMAND = 28, + MODE_EXTENDED_COMMAND_VALUE = 29, + END_COMMAND, + EXTENDED_COMMAND_BOUNDARY, +}; + +struct Token { + std::string content; + enum TokenType type; +}; + +struct CommandToken : Token {}; + +struct ExtendedCommand : Token {}; + +struct GerberTokenizer { + + class EndOfFile : std::exception {}; + + class InvalidToken : std::exception { + + std::string message; + uint64_t failure_char_index; + + public: + InvalidToken(uint64_t failure_char_index, std::string message) : + failure_char_index(failure_char_index), + message(message) {} + + const char* what() const noexcept override { + return message.c_str(); + } + }; + + enum class Result { + CONSUMED, + ABORTED, + }; + + char* gerber_code; + uint64_t gerber_code_size; + std::vector tokens_vector; + + GerberTokenizer(char* file_mapping, uint64_t file_size) : + gerber_code(file_mapping), + gerber_code_size(file_size) {} + + bool tokenize() { + uint64_t current_char_index = 0; + try { + while (current_char_index < gerber_code_size) { + current_char_index = tokenize_next(current_char_index); + } + } catch (GerberTokenizer::EndOfFile) { + return true; + } + return true; + } + + std::string make_substring(uint64_t begin_token_index, uint64_t current_char_index) { + return std::string(gerber_code + begin_token_index, gerber_code + current_char_index); + } + + void make_token(uint64_t begin_token_index, uint64_t current_char_index, enum TokenType type) { + tokens_vector.push_back({make_substring(begin_token_index, current_char_index), type}); + + std::cout << tokens_vector.back().content << " " << int(tokens_vector.back().type) + << std::endl; + } + + [[noreturn]] void throw_invalid_token(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + if (begin_token_index > 0) { + begin_token_index--; + } + if (current_char_index > 0) { + current_char_index--; + } + } + std::string message = std::format( + "Invalid token '{}' at index: {}", + make_substring(begin_token_index, current_char_index + 1), + begin_token_index + ); + throw InvalidToken(begin_token_index, message); + } + + uint64_t tokenize_next(uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw EndOfFile(); + } + char current_char = gerber_code[current_char_index]; + + switch (current_char) { + case '*': + return tokenize_asterisk(current_char_index, current_char_index); + case 'G': + return tokenize_g_code(current_char_index, current_char_index + 1); + case 'D': + return tokenize_d_code(current_char_index, current_char_index + 1); + case 'X': + case 'Y': + case 'I': + case 'J': + make_token( + current_char_index, current_char_index + 1, TokenType::COORDINATE_COMMAND + ); + return tokenize_signed_integer(current_char_index + 1, current_char_index + 1); + case '%': + make_token( + current_char_index, current_char_index + 1, TokenType::EXTENDED_COMMAND_BOUNDARY + ); + return tokenize_extended_command(current_char_index + 1, current_char_index + 1); + case ' ': + case '\t': + case '\n': + case '\r': + return current_char_index + 1; + default: + throw_invalid_token(current_char_index, current_char_index + 1); + } + throw_invalid_token(current_char_index, current_char_index + 1); + } + + uint64_t tokenize_asterisk(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '*': + make_token(begin_token_index, current_char_index + 1, TokenType::END_COMMAND); + return current_char_index + 1; + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t + tokenize_extended_command_boundary(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '%': + make_token( + begin_token_index, current_char_index + 1, TokenType::EXTENDED_COMMAND_BOUNDARY + ); + return current_char_index + 1; + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_string(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + make_token(begin_token_index, current_char_index, TokenType::STRING); + return current_char_index - 1; + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '*': + case '%': + make_token(begin_token_index, current_char_index, TokenType::STRING); + return current_char_index - 1; + default: + return tokenize_string(begin_token_index, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_g_code(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '0': + return tokenize_g_code(begin_token_index, current_char_index + 1); + case '1': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G01_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '2': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G02_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '3': + if (is_a_number(current_char_index + 1)) { + return tokenize_g3_code(begin_token_index, current_char_index + 1); + } else { + make_token(begin_token_index, current_char_index + 1, TokenType::G03_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + } + case '4': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G04_COMMAND); + if (!is_asterisk(current_char_index + 1)) { + current_char_index = + tokenize_string(current_char_index + 1, current_char_index + 1); + } + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '5': + if (is_a_number(current_char_index + 1)) { + return tokenize_g5_code(begin_token_index, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + case '7': + if (is_a_number(current_char_index + 1)) { + return tokenize_g7_code(begin_token_index, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + case '9': + if (is_a_number(current_char_index + 1)) { + return tokenize_g9_code(begin_token_index, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_g3_code(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '6': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G36_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '7': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G37_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_g5_code(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '4': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G54_COMMAND); + return current_char_index + 1; + case '5': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G55_COMMAND); + return current_char_index + 1; + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_g7_code(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '0': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G70_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '1': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G71_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '4': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G74_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '5': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G75_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_g9_code(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '0': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G90_COMMAND); + // tokenize D code. + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '1': + if (is_a_number(current_char_index + 1)) + throw_invalid_token(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::G91_COMMAND); + // tokenize D03 code. + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_d_code(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + return begin_token_index; + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '0': + return tokenize_d_code(begin_token_index, current_char_index + 1); + case '1': + if (is_a_number(current_char_index + 1)) + return tokenize_d_select(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::D01_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '2': + if (is_a_number(current_char_index + 1)) + return tokenize_d_select(begin_token_index, current_char_index + 1); + make_token(begin_token_index, current_char_index + 1, TokenType::D02_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + case '3': + if (is_a_number(current_char_index + 1)) { + return tokenize_d_select(begin_token_index, current_char_index + 1); + } else { + make_token(begin_token_index, current_char_index + 1, TokenType::D03_COMMAND); + return tokenize_asterisk(current_char_index + 1, current_char_index + 1); + } + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return tokenize_d_select(begin_token_index, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_d_select(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + return begin_token_index; + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return tokenize_d_select(begin_token_index, current_char_index + 1); + default: + make_token(begin_token_index, current_char_index, TokenType::DNN_SELECT); + return tokenize_asterisk(current_char_index, current_char_index); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_signed_integer(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + if (begin_token_index == current_char_index) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + return begin_token_index; + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '-': + case '+': + return tokenize_unsigned_integer(begin_token_index, current_char_index + 1); + default: + return tokenize_unsigned_integer(begin_token_index, current_char_index); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_unsigned_integer(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + if (begin_token_index == current_char_index) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + return begin_token_index; + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return tokenize_signed_integer(begin_token_index, current_char_index + 1); + default: + if (begin_token_index == current_char_index) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + make_token(begin_token_index, current_char_index, TokenType::INTEGER); + return current_char_index; + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_extended_command(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case 'F': + return tokenize_fs_extended_command(begin_token_index, current_char_index + 1); + case 'M': + return tokenize_mode_extended_command(begin_token_index, current_char_index + 1); + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t tokenize_fs_extended_command(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + if (current_char == 'S') { + make_token(begin_token_index, current_char_index + 1, TokenType::FS_EXTENDED_COMMAND); + current_char_index++; + begin_token_index = current_char_index; + } else { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + current_char_index = tokenize_one_of( + "LT", 2, TokenType::FS_ZERO_OMISSION, begin_token_index, current_char_index + ); + begin_token_index = current_char_index; + + current_char_index = tokenize_one_of( + "AI", 2, TokenType::FS_COORDINATE_TYPE, begin_token_index, current_char_index + ); + begin_token_index = current_char_index; + + for (int i = 0; i < 2; i++) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + current_char = gerber_code[current_char_index]; + switch (current_char) { + case 'X': + case 'Y': + make_token( + begin_token_index, current_char_index + 1, TokenType::FS_AXIS_FORMAT + ); + current_char_index = + tokenize_unsigned_integer(current_char_index + 1, current_char_index + 1); + begin_token_index = current_char_index; + break; + default: + throw_invalid_token(begin_token_index, current_char_index + 1); + } + } + + current_char_index = tokenize_asterisk(begin_token_index, current_char_index); + current_char_index = + tokenize_extended_command_boundary(current_char_index, current_char_index); + + return current_char_index + 1; + } + + uint64_t tokenize_one_of( + const char* chars, + uint32_t length, + enum TokenType token_type, + uint64_t begin_token_index, + uint64_t current_char_index + ) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + for (int i = 0; i < length; i++) { + if (current_char == chars[i]) { + make_token(begin_token_index, current_char_index + 1, token_type); + return current_char_index + 1; + } + } + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + uint64_t + tokenize_mode_extended_command(uint64_t begin_token_index, uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + char current_char = gerber_code[current_char_index]; + if (current_char != 'O') { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + make_token(begin_token_index, current_char_index + 1, TokenType::MODE_EXTENDED_COMMAND); + + current_char_index++; + begin_token_index = current_char_index; + + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + current_char = gerber_code[current_char_index]; + switch (current_char) { + case 'M': + current_char = next_or_throw(begin_token_index, current_char_index); + if (current_char != 'M') { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + make_token( + begin_token_index, + current_char_index + 1, + TokenType::MODE_EXTENDED_COMMAND_VALUE + ); + break; + case 'I': + current_char = next_or_throw(begin_token_index, current_char_index); + if (current_char != 'N') { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + make_token( + begin_token_index, + current_char_index + 1, + TokenType::MODE_EXTENDED_COMMAND_VALUE + ); + break; + default: + throw_invalid_token(begin_token_index, current_char_index + 1); + } + + current_char_index = tokenize_asterisk(current_char_index + 1, current_char_index + 1); + current_char_index = + tokenize_extended_command_boundary(current_char_index, current_char_index); + + return current_char_index + 1; + } + + char next_or_throw(uint64_t begin_token_index, uint64_t& current_char_index) { + current_char_index++; + if (current_char_index >= gerber_code_size) { + throw_invalid_token(begin_token_index, current_char_index + 1); + } + return gerber_code[current_char_index]; + } + + bool is_a_number(uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + return false; + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return true; + } + return false; + } + + bool is_asterisk(uint64_t current_char_index) { + if (current_char_index >= gerber_code_size) { + return false; + } + char current_char = gerber_code[current_char_index]; + switch (current_char) { + case '*': + return true; + } + return false; + } +}; + +int main() { + + std::vector paths = { + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G01.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G02.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G03.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G04.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G04_text." + "grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G36.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G37.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G54.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G55.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G70.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G71.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G74.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G75.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G90.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\g_codes\\G91.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\d_select\\D11.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\d_select\\D12.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\d_select\\D301.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\d_select\\D999.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\d_codes\\D01.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\d_codes\\D02.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\d_codes\\D03.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\fs\\FSLAX26Y26.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\fs\\FSLAX66Y66.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\fs\\FSLIX26Y26.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\fs\\FSTIX26Y27.grb", + "C:\\Users\\argma\\dev\\pygerber\\test\\assets\\gerberx3\\tokens\\set_codes\\mo.grb", + }; + for (auto path : paths) { + auto mapping_handler = FileMapping(path.c_str()); + char* mapping = (char*)(mapping_handler.GetMapping()); + + auto size = mapping_handler.GetSize(); + std::cout << path << std::endl; + GerberTokenizer tokenizer(mapping, size); + tokenizer.tokenize(); + // for (auto token : tokenizer.tokenized_tokens_vector) { + // std::cout << token.content << " " << int(token.type) << std::endl; + // } + } + + return 0; +} diff --git a/output.jpeg b/output.jpeg new file mode 100644 index 00000000..47756e8a Binary files /dev/null and b/output.jpeg differ diff --git a/output.svg b/output.svg new file mode 100644 index 00000000..9ea00d18 --- /dev/null +++ b/output.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/assets/gerberx3/tokens/d_codes/D01.grb b/test/assets/gerberx3/tokens/d_codes/D01.grb new file mode 100644 index 00000000..e9a837c5 --- /dev/null +++ b/test/assets/gerberx3/tokens/d_codes/D01.grb @@ -0,0 +1,2 @@ +X0000000Y2000000D01* +X060000Y000000I000000J060000D01* diff --git a/test/assets/gerberx3/tokens/d_codes/D02.grb b/test/assets/gerberx3/tokens/d_codes/D02.grb new file mode 100644 index 00000000..d13d35f4 --- /dev/null +++ b/test/assets/gerberx3/tokens/d_codes/D02.grb @@ -0,0 +1 @@ +X0000000Y2000000D02* diff --git a/test/assets/gerberx3/tokens/d_codes/D03.grb b/test/assets/gerberx3/tokens/d_codes/D03.grb new file mode 100644 index 00000000..2fa0782c --- /dev/null +++ b/test/assets/gerberx3/tokens/d_codes/D03.grb @@ -0,0 +1 @@ +X1500000Y1500000D03* diff --git a/test/assets/gerberx3/tokens/d_select/D11.grb b/test/assets/gerberx3/tokens/d_select/D11.grb new file mode 100644 index 00000000..e529776d --- /dev/null +++ b/test/assets/gerberx3/tokens/d_select/D11.grb @@ -0,0 +1,2 @@ +D11* +D011* diff --git a/test/assets/gerberx3/tokens/d_select/D12.grb b/test/assets/gerberx3/tokens/d_select/D12.grb new file mode 100644 index 00000000..e4d7933a --- /dev/null +++ b/test/assets/gerberx3/tokens/d_select/D12.grb @@ -0,0 +1,2 @@ +D12* +D012* diff --git a/test/assets/gerberx3/tokens/d_select/D301.grb b/test/assets/gerberx3/tokens/d_select/D301.grb new file mode 100644 index 00000000..5429c1d3 --- /dev/null +++ b/test/assets/gerberx3/tokens/d_select/D301.grb @@ -0,0 +1,2 @@ +D301* +D0301* diff --git a/test/assets/gerberx3/tokens/d_select/D999.grb b/test/assets/gerberx3/tokens/d_select/D999.grb new file mode 100644 index 00000000..690601c0 --- /dev/null +++ b/test/assets/gerberx3/tokens/d_select/D999.grb @@ -0,0 +1,2 @@ +D999* +D0999* diff --git a/test/assets/gerberx3/tokens/fs/FSLAX26Y26.grb b/test/assets/gerberx3/tokens/fs/FSLAX26Y26.grb new file mode 100644 index 00000000..ba50de88 --- /dev/null +++ b/test/assets/gerberx3/tokens/fs/FSLAX26Y26.grb @@ -0,0 +1 @@ +%FSLAX26Y26*% diff --git a/test/assets/gerberx3/tokens/fs/FSLAX66Y66.grb b/test/assets/gerberx3/tokens/fs/FSLAX66Y66.grb new file mode 100644 index 00000000..e9f73c69 --- /dev/null +++ b/test/assets/gerberx3/tokens/fs/FSLAX66Y66.grb @@ -0,0 +1 @@ +%FSLIX66Y66*% diff --git a/test/assets/gerberx3/tokens/fs/FSLIX26Y26.grb b/test/assets/gerberx3/tokens/fs/FSLIX26Y26.grb new file mode 100644 index 00000000..9211cacd --- /dev/null +++ b/test/assets/gerberx3/tokens/fs/FSLIX26Y26.grb @@ -0,0 +1 @@ +%FSLAX66Y66*% diff --git a/test/assets/gerberx3/tokens/fs/FSTIX26Y27.grb b/test/assets/gerberx3/tokens/fs/FSTIX26Y27.grb new file mode 100644 index 00000000..e2b95967 --- /dev/null +++ b/test/assets/gerberx3/tokens/fs/FSTIX26Y27.grb @@ -0,0 +1 @@ +%FSTAX66Y66*% diff --git a/test/assets/gerberx3/tokens/g_codes/G01.grb b/test/assets/gerberx3/tokens/g_codes/G01.grb new file mode 100644 index 00000000..f06a0644 --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G01.grb @@ -0,0 +1,3 @@ +G1* +G01* +G001* diff --git a/test/assets/gerberx3/tokens/g_codes/G02.grb b/test/assets/gerberx3/tokens/g_codes/G02.grb new file mode 100644 index 00000000..9d6ca973 --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G02.grb @@ -0,0 +1,3 @@ +G2* +G02* +G002* diff --git a/test/assets/gerberx3/tokens/g_codes/G03.grb b/test/assets/gerberx3/tokens/g_codes/G03.grb new file mode 100644 index 00000000..c7bfeb5e --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G03.grb @@ -0,0 +1,3 @@ +G3* +G03* +G003* diff --git a/test/assets/gerberx3/tokens/g_codes/G04.grb b/test/assets/gerberx3/tokens/g_codes/G04.grb new file mode 100644 index 00000000..836f326c --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G04.grb @@ -0,0 +1,3 @@ +G4* +G04* +G004* diff --git a/test/assets/gerberx3/tokens/g_codes/G04_text.grb b/test/assets/gerberx3/tokens/g_codes/G04_text.grb new file mode 100644 index 00000000..5dde3b7a --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G04_text.grb @@ -0,0 +1,2 @@ +G04 Comment text :D * +G04Comment text :D* diff --git a/test/assets/gerberx3/tokens/g_codes/G36.grb b/test/assets/gerberx3/tokens/g_codes/G36.grb new file mode 100644 index 00000000..53b5748d --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G36.grb @@ -0,0 +1,2 @@ +G36* +G036* diff --git a/test/assets/gerberx3/tokens/g_codes/G37.grb b/test/assets/gerberx3/tokens/g_codes/G37.grb new file mode 100644 index 00000000..6b7cf47d --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G37.grb @@ -0,0 +1,2 @@ +G37* +G037* diff --git a/test/assets/gerberx3/tokens/g_codes/G54.grb b/test/assets/gerberx3/tokens/g_codes/G54.grb new file mode 100644 index 00000000..eacc17f9 --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G54.grb @@ -0,0 +1,2 @@ +G54D11* +G054D11* diff --git a/test/assets/gerberx3/tokens/g_codes/G55.grb b/test/assets/gerberx3/tokens/g_codes/G55.grb new file mode 100644 index 00000000..975517c2 --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G55.grb @@ -0,0 +1,2 @@ +G55X0Y0D03* +G055X0Y0D03* diff --git a/test/assets/gerberx3/tokens/g_codes/G70.grb b/test/assets/gerberx3/tokens/g_codes/G70.grb new file mode 100644 index 00000000..e11c6a97 --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G70.grb @@ -0,0 +1,2 @@ +G70* +G070* diff --git a/test/assets/gerberx3/tokens/g_codes/G71.grb b/test/assets/gerberx3/tokens/g_codes/G71.grb new file mode 100644 index 00000000..f14637a2 --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G71.grb @@ -0,0 +1,2 @@ +G71* +G071* diff --git a/test/assets/gerberx3/tokens/g_codes/G74.grb b/test/assets/gerberx3/tokens/g_codes/G74.grb new file mode 100644 index 00000000..d6cc6c2b --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G74.grb @@ -0,0 +1,2 @@ +G74* +G074* diff --git a/test/assets/gerberx3/tokens/g_codes/G75.grb b/test/assets/gerberx3/tokens/g_codes/G75.grb new file mode 100644 index 00000000..6eea0067 --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G75.grb @@ -0,0 +1,2 @@ +G75* +G075* diff --git a/test/assets/gerberx3/tokens/g_codes/G90.grb b/test/assets/gerberx3/tokens/g_codes/G90.grb new file mode 100644 index 00000000..56d26994 --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G90.grb @@ -0,0 +1,2 @@ +G90* +G090* diff --git a/test/assets/gerberx3/tokens/g_codes/G91.grb b/test/assets/gerberx3/tokens/g_codes/G91.grb new file mode 100644 index 00000000..1f41ef3f --- /dev/null +++ b/test/assets/gerberx3/tokens/g_codes/G91.grb @@ -0,0 +1,2 @@ +G91* +G091* diff --git a/test/assets/gerberx3/tokens/set_codes/as.grb b/test/assets/gerberx3/tokens/set_codes/as.grb new file mode 100644 index 00000000..db7c052d --- /dev/null +++ b/test/assets/gerberx3/tokens/set_codes/as.grb @@ -0,0 +1,2 @@ +%ASAYBX*% +%ASAXBY*% diff --git a/test/assets/gerberx3/tokens/set_codes/mo.grb b/test/assets/gerberx3/tokens/set_codes/mo.grb new file mode 100644 index 00000000..a034bf6a --- /dev/null +++ b/test/assets/gerberx3/tokens/set_codes/mo.grb @@ -0,0 +1,2 @@ +%MOMM*% +%MOIN*% diff --git a/test/gerberx3/test_rasterized_2d/reference/basic/sample-5/source.1/image.png b/test/gerberx3/test_rasterized_2d/reference/basic/sample-5/source.1/image.png new file mode 100644 index 00000000..8eb4f0e0 Binary files /dev/null and b/test/gerberx3/test_rasterized_2d/reference/basic/sample-5/source.1/image.png differ