#include #include #include #include namespace regexis024 { #define nonthrowing_assert(expr) if (!(expr)) {error = -1; return; } void compilation_core(std::vector& result, FA_Container& fa, explicit_bookmarks& bookmark_manager, size_t& read_ss_ns, size_t& fork_ss_ns, int& error) { bookmark_id_t node_start_bm_offset = bookmark_manager.new_range_of_bookmarks(fa.all.size()); read_ss_ns = 0; fork_ss_ns = 0; assert(fa.start); std::vector todo = {fa.start}; auto nodesBookmark = [&](FA_Node* node) -> bookmark_id_t { assert(node); return node_start_bm_offset + node->nodeId; }; auto addBranching = [&](FA_Node* node) { todo.push_back(node); }; while (!todo.empty()) { FA_Node* node = todo.back(); todo.pop_back(); if (bookmark_manager.has_landed(nodesBookmark(node))) { continue; } while (true) { if (bookmark_manager.has_landed(nodesBookmark(node))) { cmd_JUMP(result, bookmark_manager, nodesBookmark(node)); break; } bookmark_manager.land_bookmark(result, nodesBookmark(node)); if (node->type == match) { cmd_MATCH(result); cmd_DIE(result); break; } else if (node->type == one_char_read) { FA_NodeOfOneCharRead* ocr = dynamic_cast(node); nonthrowing_assert(read_ss_ns < UINT32_MAX); cmd_READ(result, read_ss_ns++); addBranching(ocr->nxt_node); bool can_spill = write_filter(result, bookmark_manager, {ocr->filter},{nodesBookmark(ocr->nxt_node)}); if (!can_spill) break; node = ocr->nxt_node; } else if (node->type == look_one_behind) { FA_NodeOfLookOneBehind* lob = dynamic_cast(node); addBranching(lob->nxt_node); bool can_spill = write_filter(result, bookmark_manager, {lob->filter}, {nodesBookmark(lob->nxt_node)}); if (!can_spill) break; node = lob->nxt_node; } else if (node->type == forking) { FA_NodeOfForking* fn = dynamic_cast(node); std::vector& nxt_options = fn->nxt_options; if (nxt_options.empty()) { cmd_DIE(result); break; } if (nxt_options.size() >= 2) { nonthrowing_assert(fork_ss_ns < UINT32_MAX); sslot_id_t sslot = fork_ss_ns++; for (size_t i = 0; i + 1 < nxt_options.size(); i++) { cmd_FORK(result, bookmark_manager, sslot, nodesBookmark(nxt_options[i])); addBranching(nxt_options[i]); } } node = nxt_options.back(); } else if (node->type == track_array_mov_imm) { FA_NodeOfTrackArrayMovImm* tami = dynamic_cast(node); write_byte(result, tami->operation); write_tai(result, tami->key); write_quadword(result, tami->imm_value); node = tami->nxt_node; } else if (node->type == track_array_mov_halfinvariant) { FA_NodeOfTrackArrayMovHalfinvariant* tamh = dynamic_cast(node); write_byte(result, tamh->operation); write_tai(result, tamh->key); node = tamh->nxt_node; } else if (node->type == det_char_crossroads) { FA_NodeOfDetCharCrossroads* dcc = dynamic_cast(node); nonthrowing_assert(read_ss_ns < UINT32_MAX); if (dcc->matching) cmd_MATCH(result); cmd_READ(result, read_ss_ns++); std::vector codesets; std::vector branches; for (const DFA_CrossroadPath& p: dcc->crossroads) { codesets.push_back(p.input); branches.push_back(nodesBookmark(p.nxt_node)); addBranching(p.nxt_node); } bool can_spill = write_filter(result, bookmark_manager, codesets, branches); if (!can_spill) break; if (dcc->crossroads.empty()) break; node = dcc->crossroads[0].nxt_node; } else assert(false); } } } }