void AST::build_stmt(ASTNode *parent, Node *node) { switch (node->children[0]->token.type) { case Token::KW_VAR: build_var_init(parent, node); break; case Token::IDENTIFIER: build_insert(parent, node); break; case Token::KW_FOR: build_for_loop(parent, node); break; case Token::KW_READ: build_read(parent, node); break; case Token::KW_PRINT: build_print(parent, node); break; case Token::KW_ASSERT: build_assert(parent, node); break; default: std::string e_str = "AST::build_stmt - Invalid token node location in parse tree for token type "; report_error(e_str.append(node->children[0]->token.type_str())); } }
static uint8_t handle_u16_read(uint16_t (*getter)(void)) { struct conf_context *pc = &conf; uint16_t value; uint8_t ret; build_assert(ARRAY_SIZE(pc->buf) >= 2); if (pc->count == 0) { value = getter(); pc->buf[0] = (uint8_t)value; pc->buf[1] = (uint8_t)(value >> 8); }
/* Build the search tree, and return the root node. @keywords - keyword list. @num - num of keywords in @keywords list. @fifo_init_size - In order to perform breath-first-search, the reserved fifo's initial size. */ int sakuc_multi_pattern_build_search_automaton (struct trie_node **root, const char *keywords[], size_t num, size_t fifo_init_size) { build_assert(*root = _new_trie_node(0)); (*root)->failover = *root; const char *keyword = nullptr; struct trie_node *current_node = nullptr; // build the tree based on prefix. for (size_t i=0; i < num; i++) { keyword = keywords[i]; current_node = *root; struct trie_node *new_node = nullptr; struct trie_node *last_child = nullptr; // handle the @keyword, "merge" it into the search tree for (size_t j=0; j < strlen(keyword); j++) { _find_child(current_node, keyword[j], &new_node, &last_child); if (new_node == nullptr) { build_assert(new_node = _new_trie_node(keyword[j])); // notice: all the newly created node's @failover is set to root by default. new_node->failover = *root; if (last_child == nullptr) current_node->first_child = new_node; else last_child->next_sibling = new_node; } current_node = new_node; } current_node->num_keywords = 1; // at most 1 currently, when building failover relationship, // @num_keywords might be increased. current_node->keyword = keyword; // const char *keyword within param @keywords } // build the failover relationship based on the tree built just now, using BFS. struct sakuc_deque *dq = nullptr; build_assert(dq = sakuc_deque_new(fifo_init_size, sizeof(pointer_trie_node_t), SAKUC_DEQUE_SWEEP_MANUALLY)); build_assert(sakuc_deque_push_back(dq, root, sizeof (pointer_trie_node_t)) == 0); _print_deque_for_debug_only(dq); while (sakuc_deque_size(dq)) { build_assert(sakuc_deque_pop_front(dq, ¤t_node, sizeof(pointer_trie_node_t)) == 0); _print_deque_for_debug_only(dq); struct trie_node *child = current_node->first_child; struct trie_node *curr_failover = nullptr; // cannot be nullptr, default to be root node. for (; child != nullptr; child = child->next_sibling) { // push_back into the queue, then process the child node. build_assert(sakuc_deque_push_back(dq, &child, sizeof(pointer_trie_node_t)) == 0); _print_deque_for_debug_only(dq); struct trie_node *x = nullptr; do { curr_failover = (curr_failover == nullptr) ? current_node->failover : curr_failover->failover; build_assert(_find_child(curr_failover, child->ch, &x, nullptr) == 0); if (x && x != child) { child->failover = x; // @failover changed from the default root node, to x node. if (x->num_keywords > 0) { child->num_keywords += x->num_keywords; } break; } } while (curr_failover != *root); curr_failover = nullptr; } } sakuc_deque_destroy(dq); return 0; sakuc_build_automaton_failed: if (dq) sakuc_deque_destroy(dq); if (*root) sakuc_multi_pattern_destroy_search_automaton(*root, fifo_init_size); *root = nullptr; return -1; }