#include "eval.h" #include #include #include "pattern.h" #include "pairmap.h" #define EVAL_FOREACH_MALLOC 1 static liblex_result foreach_errors[2] = { LIBLEX_SUCCESS, LIBLEX_MALLOC }; void eval_config_init(eval_config* config){ ll_init(&config->states); } liblex_result eval_config_add(eval_config* config, char* ptrn, int pattern_id){ liblex_result result; pattern* new_pattern = malloc(sizeof(*new_pattern)); if(new_pattern){ result = pattern_compile(new_pattern, ptrn, pattern_id); if(result == LIBLEX_SUCCESS){ result = (ll_append(&config->states, new_pattern) == LIBDS_SUCCESS) ? LIBLEX_SUCCESS : LIBLEX_MALLOC; } if(result != LIBLEX_SUCCESS){ pattern_free(new_pattern); free(new_pattern); } } else { result = LIBLEX_MALLOC; } return result; } int eval_foreach_match_free(void* data, va_list args) { free(data); return 0; } int eval_config_foreach_free(void* data, va_list args){ pattern* ptrn = data; int result = pattern_free(ptrn) == LIBLEX_SUCCESS ? 0 : EVAL_FOREACH_MALLOC; free(ptrn); return result; } liblex_result eval_config_free(eval_config* config){ liblex_result result = foreach_errors[ll_foreach(&config->states, NULL, compare_always, eval_config_foreach_free)]; ll_free(&config->states); return result; } pattern_node* eval_pattern_node_get_next(pattern_node* node){ pattern_node* to_return = NULL; if(node->type == PNODE_VALUE){ to_return = node->data_u.value_s.next; } else if(node->type == PNODE_ANY){ to_return = node->data_u.any_s.next; } else if(node->type == PNODE_RANGE){ to_return = node->data_u.range_s.next; } else if(node->type == PNODE_CONNECT){ to_return = node->data_u.connect_s.next; } return to_return; } liblex_result eval_pairmap_add_node(ht* table, pattern_node* node){ liblex_result result = LIBLEX_SUCCESS; if(node->type == PNODE_ANY || node->type == PNODE_VALUE || node->type == PNODE_RANGE || node->type == PNODE_END){ pairmap_key tmp_key; result = PAIRMAP_PUT(table, &tmp_key, node->pattern_id, node->id, node) == LIBDS_SUCCESS ? LIBLEX_SUCCESS : LIBLEX_MALLOC; } else if(node->type == PNODE_CONNECT){ result = eval_pairmap_add_node(table, eval_pattern_node_get_next(node)); } else if(node->type == PNODE_FORK){ result = eval_pairmap_add_node(table, node->data_u.fork_s.left); if(result == LIBDS_SUCCESS){ result = eval_pairmap_add_node(table, node->data_u.fork_s.right); } } return result; } int eval_foreach_add_node(void* data, va_list args){ pattern* new_pattern = data; ht* pairmap = va_arg(args, ht*); pattern_node* pattern_head = new_pattern->head; return eval_pairmap_add_node(pairmap, pattern_head) == LIBLEX_SUCCESS? 0 : EVAL_FOREACH_MALLOC; } int eval_node_matches(pattern_node* node, eval* eval){ int matches = 0; char value = eval->string[eval->index]; if(node->type == PNODE_ANY){ matches = value != '\0'; } else if(node->type == PNODE_VALUE){ matches = value == node->data_u.value_s.value; } else if(node->type == PNODE_RANGE) { matches = value >= node->data_u.range_s.from && value <= node->data_u.range_s.to; } return matches; } int eval_foreach_check_state(void* data, va_list args){ int return_code = 0; pattern_node* node = data; eval* evl = va_arg(args, eval*); if(eval_node_matches(node, evl)){ return_code = eval_pairmap_add_node(evl->set_next, eval_pattern_node_get_next(node)) == LIBLEX_SUCCESS ? 0 : EVAL_FOREACH_MALLOC; if(return_code == 0){ evl->matched++; } } else if(node->type == PNODE_END){ match* new_match = malloc(sizeof(*new_match)); if(new_match){ new_match->from = evl->begin; new_match->to = evl->index; new_match->pattern = node->pattern_id; return_code = ll_append(&evl->matches, new_match) == LIBLEX_SUCCESS ? 0 : EVAL_FOREACH_MALLOC; if(return_code){ free(new_match); } } else { return_code = EVAL_FOREACH_MALLOC; } } return return_code; } liblex_result eval_step(eval* eval){ ht* tmp; eval->matched = 0; liblex_result result = foreach_errors[ht_foreach(eval->set_current, NULL, compare_always, eval_foreach_check_state, eval)]; tmp = eval->set_current; eval->set_current = eval->set_next; eval->set_next = tmp; eval->index++; ht_free(eval->set_next); pairmap_init_ht(eval->set_next); return result; } liblex_result eval_word(char* string, int index, eval_config* config, match* mtch){ liblex_result result = LIBLEX_SUCCESS; eval evl; evl.index = evl.begin = index; evl.string = string; evl.matched = 0; pairmap_init_ht(&evl.set_a); pairmap_init_ht(&evl.set_b); ll_init(&evl.matches); evl.set_current = &evl.set_a; evl.set_next = &evl.set_b; ll_foreach(&config->states, NULL, compare_always, eval_foreach_add_node, evl.set_current); do { eval_step(&evl); } while(evl.matched); if(evl.matches.tail){ match* largest_match = evl.matches.tail->data; mtch->from = largest_match->from; mtch->to = largest_match->to; mtch->pattern = mtch->pattern; } else { mtch->from = -1; mtch->to = -1; mtch->pattern = -1; } ll_foreach(&evl.matches, NULL, compare_always, eval_foreach_match_free); ll_free(&evl.matches); ht_free(&evl.set_a); ht_free(&evl.set_b); return result; } liblex_result eval_all(char* string, int index, eval_config* config, ll* matches){ liblex_result result = LIBLEX_SUCCESS; return result; }