Compare commits

...

5 Commits

4 changed files with 135 additions and 12 deletions

View File

@@ -74,9 +74,26 @@ struct eval_config_s {
ll states; ll states;
}; };
/**
* Information about a state that has been
* added with eval_config_add.
*/
struct eval_state_s {
/**
* The string that was used to compile
* this state.
*/
const char* source;
/**
* The pattern that was generated with this state.
*/
pattern* pattern;
};
typedef struct match_s match; typedef struct match_s match;
typedef struct eval_s eval; typedef struct eval_s eval;
typedef struct eval_config_s eval_config; typedef struct eval_config_s eval_config;
typedef struct eval_state_s eval_state;
/** /**
* Initializes the evaluation configuration. * Initializes the evaluation configuration.
@@ -97,6 +114,15 @@ liblex_result eval_config_free(eval_config* config);
* @return LIBLEX_SUCCESS if all goes well, or LIBLEX_MALLOC if there was an allocation failure. * @return LIBLEX_SUCCESS if all goes well, or LIBLEX_MALLOC if there was an allocation failure.
*/ */
liblex_result eval_config_add(eval_config* config, const char* pattern, int pattern_id); liblex_result eval_config_add(eval_config* config, const char* pattern, int pattern_id);
/**
* Removes a pattern from this configuration that has been previously
* registered.
* @param config the configuration to add the pattern to.
* @param pattern the pattern to remove.
* @param pattern_id the id associated with the pattern.
* @return LIBLEX_SUCCESS if all goes well, or LIBLEX_MALLOC if there was an allocation failure.
*/
liblex_result eval_config_remove(eval_config* config, const char* pattern, int pattern_id);
/** /**
* Evaluates / finds a single word. * Evaluates / finds a single word.
* @param string the string to evaluate. * @param string the string to evaluate.

View File

@@ -56,6 +56,11 @@ struct pattern_node_s {
* The id of the pattern that this node belongs to. * The id of the pattern that this node belongs to.
*/ */
int pattern_id; int pattern_id;
/**
* Whether to "invert" this node - inverted
* nodes indicate "match anything but this".
*/
int invert;
/** /**
* The node's data that varies based on type. * The node's data that varies based on type.

View File

@@ -16,28 +16,59 @@ void eval_config_init(eval_config* config){
} }
liblex_result eval_config_add(eval_config* config, const char* ptrn, int pattern_id){ liblex_result eval_config_add(eval_config* config, const char* ptrn, int pattern_id){
liblex_result result; liblex_result result;
pattern* new_pattern = malloc(sizeof(*new_pattern)); pattern* new_pattern;
if(new_pattern){ eval_state* new_state;
new_pattern = malloc(sizeof(*new_pattern));
new_state = malloc(sizeof(*new_pattern));
if(new_pattern && new_state){
result = pattern_compile(new_pattern, ptrn, pattern_id); result = pattern_compile(new_pattern, ptrn, pattern_id);
if(result == LIBLEX_SUCCESS){ if(result == LIBLEX_SUCCESS){
result = (ll_append(&config->states, new_pattern) == LIBDS_SUCCESS) ? new_state->source = ptrn;
new_state->pattern = new_pattern;
result = (ll_append(&config->states, new_state) == LIBDS_SUCCESS) ?
LIBLEX_SUCCESS : LIBLEX_MALLOC; LIBLEX_SUCCESS : LIBLEX_MALLOC;
} }
if(result != LIBLEX_SUCCESS){ if(result != LIBLEX_SUCCESS){
pattern_free(new_pattern); pattern_free(new_pattern);
free(new_pattern);
} }
} else { } else {
result = LIBLEX_MALLOC; result = LIBLEX_MALLOC;
} }
if(result != LIBLEX_SUCCESS) {
free(new_pattern);
free(new_state);
}
return result;
}
liblex_result _eval_config_free_state(eval_state* state) {
liblex_result result = pattern_free(state->pattern);
free(state->pattern);
free(state);
return result;
}
liblex_result eval_config_remove(eval_config* config, const char* pattern, int pattern_id) {
liblex_result result = LIBLEX_SUCCESS;
ll_node* head = config->states.head;
while(head && result == LIBLEX_SUCCESS) {
eval_state* current_state = head->data;
if(strcmp(current_state->source, pattern) == 0 && current_state->pattern->head->pattern_id == pattern_id) {
ll_node* to_delete = head;
head = head->next;
*(to_delete->prev ? &to_delete->prev->next : &(config->states.head)) = to_delete->next;
*(to_delete->next ? &to_delete->next->prev : &(config->states.tail)) = to_delete->prev;
free(to_delete);
result = _eval_config_free_state(current_state);
} else {
head = head->next;
}
}
return result; return result;
} }
int _eval_config_foreach_free(void* data, va_list args){ int _eval_config_foreach_free(void* data, va_list args){
pattern* ptrn = data; return _eval_config_free_state(data) == LIBLEX_SUCCESS ? 0 : EVAL_FOREACH_MALLOC;
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 eval_config_free(eval_config* config){
@@ -79,9 +110,9 @@ liblex_result _eval_pairmap_add_node(ht *table, pattern_node *node){
} }
int _eval_foreach_add_node(void *data, va_list args){ int _eval_foreach_add_node(void *data, va_list args){
pattern* new_pattern = data; eval_state* state = data;
ht* pairmap = va_arg(args, ht*); ht* pairmap = va_arg(args, ht*);
pattern_node* pattern_head = new_pattern->head; pattern_node* pattern_head = state->pattern->head;
return _eval_pairmap_add_node(pairmap, pattern_head) == LIBLEX_SUCCESS? 0 : EVAL_FOREACH_MALLOC; return _eval_pairmap_add_node(pairmap, pattern_head) == LIBLEX_SUCCESS? 0 : EVAL_FOREACH_MALLOC;
} }
@@ -99,10 +130,15 @@ int _eval_node_matches(pattern_node *node, eval *eval){
} }
int _eval_foreach_check_node(void *data, va_list args){ int _eval_foreach_check_node(void *data, va_list args){
int inverted_matches = 1;
int return_code = 0; int return_code = 0;
pattern_node* node = data; pattern_node* node = data;
eval* evl = va_arg(args, eval*); eval* evl = va_arg(args, eval*);
if(_eval_node_matches(node, evl)){ while(node && node->invert && inverted_matches) {
inverted_matches &= !_eval_node_matches(node, evl);
node = _eval_pattern_node_get_next(node);
}
if(inverted_matches && _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; 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){ if(return_code == 0){
evl->matched++; evl->matched++;

View File

@@ -9,6 +9,7 @@ void _pattern_node_clear(pattern_node* to_clear){
to_clear->type = PNODE_CLEAR; to_clear->type = PNODE_CLEAR;
to_clear->id = -1; to_clear->id = -1;
to_clear->pattern_id = -1; to_clear->pattern_id = -1;
to_clear->invert = 0;
memset(&(to_clear->data_u), 0, sizeof(to_clear->data_u)); memset(&(to_clear->data_u), 0, sizeof(to_clear->data_u));
} }
@@ -195,6 +196,57 @@ liblex_result _pattern_read_value(char* read_into, const char* string, int* inde
return result; return result;
} }
liblex_result _pattern_build_inverted_or(pattern_chain** into, int* ids, int pattern_id, const char* string, int* index) {
pattern_node* new_node = NULL;
liblex_result result = LIBLEX_SUCCESS;
result = _pattern_chain_create(into, NULL, NULL);
if(result == LIBLEX_SUCCESS){
(*index)++;
if(string[*index]) (*index)++;
}
while(string[*index] && string[*index] != ']' && result == LIBDS_SUCCESS) {
char from = '\0';
char to = '\0';
result = _pattern_read_value(&from, string, index);
if(result == LIBLEX_SUCCESS && string[*index] == '-') {
(*index)++;
result = _pattern_read_value(&to, string, index);
}
if(result == LIBLEX_SUCCESS) {
if(to) {
result = _pattern_node_create_range(&new_node, (*ids)++, pattern_id, from, to, NULL);
} else {
result = _pattern_node_create_value(&new_node, (*ids)++, pattern_id, from, NULL);
}
}
if(result == LIBLEX_SUCCESS) {
new_node->invert = 1;
_pattern_chain_append_node(*into, new_node);
}
}
if(result == LIBLEX_SUCCESS) {
result = _pattern_node_create_any(&new_node, (*ids)++, pattern_id, NULL);
if(result == LIBLEX_SUCCESS) {
_pattern_chain_append_node(*into, new_node);
}
}
if(result != LIBLEX_SUCCESS) {
if(*into && (*into)->head) {
_pattern_free((*into)->head, *ids);
}
free(*into);
} else {
(*index)++;
}
return result;
}
liblex_result _pattern_build_or(pattern_chain** into, int* ids, int pattern_id, const char* string, int* index) { liblex_result _pattern_build_or(pattern_chain** into, int* ids, int pattern_id, const char* string, int* index) {
pattern_node *tail_node; pattern_node *tail_node;
liblex_result result = LIBLEX_SUCCESS; liblex_result result = LIBLEX_SUCCESS;
@@ -284,7 +336,11 @@ liblex_result _pattern_build_chain(pattern_chain** into, int* ids, int pattern_i
result = _pattern_build_chain(&sub_chain, ids, pattern_id, string, index); result = _pattern_build_chain(&sub_chain, ids, pattern_id, string, index);
} else if(string[*index] == '['){ } else if(string[*index] == '['){
_pattern_chain_append_chain_discard(current_chain, &sub_chain); _pattern_chain_append_chain_discard(current_chain, &sub_chain);
if(string[(*index) + 1] == '^') {
result = _pattern_build_inverted_or(&sub_chain, ids, pattern_id, string, index);
} else {
result = _pattern_build_or(&sub_chain, ids, pattern_id, string, index); result = _pattern_build_or(&sub_chain, ids, pattern_id, string, index);
}
} else if(string[*index] == '?' || string[*index] == '*' || string[*index] == '+'){ } else if(string[*index] == '?' || string[*index] == '*' || string[*index] == '+'){
if(sub_chain != NULL && sub_chain->head){ if(sub_chain != NULL && sub_chain->head){
pattern_node* connection_node = NULL; pattern_node* connection_node = NULL;