diff --git a/include/pattern.h b/include/pattern.h index c267c0c..0dcc287 100644 --- a/include/pattern.h +++ b/include/pattern.h @@ -56,6 +56,11 @@ struct pattern_node_s { * The id of the pattern that this node belongs to. */ 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. diff --git a/src/pattern.c b/src/pattern.c index 4ba4a8d..cf6e394 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -9,6 +9,7 @@ void _pattern_node_clear(pattern_node* to_clear){ to_clear->type = PNODE_CLEAR; to_clear->id = -1; to_clear->pattern_id = -1; + to_clear->invert = 0; 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; } +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) { pattern_node *tail_node; 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); } else if(string[*index] == '['){ _pattern_chain_append_chain_discard(current_chain, &sub_chain); - result = _pattern_build_or(&sub_chain, ids, pattern_id, string, index); + 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); + } } else if(string[*index] == '?' || string[*index] == '*' || string[*index] == '+'){ if(sub_chain != NULL && sub_chain->head){ pattern_node* connection_node = NULL;