|
/* retoor <retoor@molodetz.nl> */
|
|
#include "ast.h"
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
|
|
static ast_node_t *ast_create_node(ast_type_t type) {
|
|
ast_node_t *node = malloc(sizeof(ast_node_t));
|
|
if (!node) return NULL;
|
|
node->type = type;
|
|
node->value = '\0';
|
|
node->left = NULL;
|
|
node->right = NULL;
|
|
node->group_id = -1;
|
|
node->bracket = NULL;
|
|
node->quant.min = 0;
|
|
node->quant.max = -1;
|
|
node->quant.greedy = true;
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_char(char c) {
|
|
ast_node_t *node = ast_create_node(AST_CHAR);
|
|
if (node) node->value = c;
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_dot(void) {
|
|
return ast_create_node(AST_DOT);
|
|
}
|
|
|
|
ast_node_t *ast_create_concat(ast_node_t *left, ast_node_t *right) {
|
|
ast_node_t *node = ast_create_node(AST_CONCAT);
|
|
if (node) {
|
|
node->left = left;
|
|
node->right = right;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_alter(ast_node_t *left, ast_node_t *right) {
|
|
ast_node_t *node = ast_create_node(AST_ALTER);
|
|
if (node) {
|
|
node->left = left;
|
|
node->right = right;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_star(ast_node_t *child, bool greedy) {
|
|
ast_node_t *node = ast_create_node(AST_STAR);
|
|
if (node) {
|
|
node->left = child;
|
|
node->quant.greedy = greedy;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_plus(ast_node_t *child, bool greedy) {
|
|
ast_node_t *node = ast_create_node(AST_PLUS);
|
|
if (node) {
|
|
node->left = child;
|
|
node->quant.greedy = greedy;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_question(ast_node_t *child, bool greedy) {
|
|
ast_node_t *node = ast_create_node(AST_QUESTION);
|
|
if (node) {
|
|
node->left = child;
|
|
node->quant.greedy = greedy;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_group(ast_node_t *child, int group_id) {
|
|
ast_node_t *node = ast_create_node(AST_GROUP);
|
|
if (node) {
|
|
node->left = child;
|
|
node->group_id = group_id;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_anchor_start(void) {
|
|
return ast_create_node(AST_ANCHOR_START);
|
|
}
|
|
|
|
ast_node_t *ast_create_anchor_end(void) {
|
|
return ast_create_node(AST_ANCHOR_END);
|
|
}
|
|
|
|
ast_node_t *ast_create_bracket(bracket_class_t *bracket) {
|
|
ast_node_t *node = ast_create_node(AST_BRACKET);
|
|
if (node) node->bracket = bracket;
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_quantifier(ast_node_t *child, int min, int max, bool greedy) {
|
|
ast_node_t *node = ast_create_node(AST_QUANTIFIER);
|
|
if (node) {
|
|
node->left = child;
|
|
node->quant.min = min;
|
|
node->quant.max = max;
|
|
node->quant.greedy = greedy;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
ast_node_t *ast_create_class(ast_type_t type) {
|
|
return ast_create_node(type);
|
|
}
|
|
|
|
void ast_free(ast_node_t *node) {
|
|
if (!node) return;
|
|
ast_free(node->left);
|
|
ast_free(node->right);
|
|
if (node->bracket) bracket_free(node->bracket);
|
|
free(node);
|
|
}
|
|
|
|
bracket_class_t *bracket_create(void) {
|
|
bracket_class_t *bracket = malloc(sizeof(bracket_class_t));
|
|
if (!bracket) return NULL;
|
|
bracket->ranges = NULL;
|
|
bracket->count = 0;
|
|
bracket->capacity = 0;
|
|
bracket->negated = false;
|
|
return bracket;
|
|
}
|
|
|
|
static bool bracket_grow(bracket_class_t *bracket) {
|
|
size_t new_cap = bracket->capacity == 0 ? 8 : bracket->capacity * 2;
|
|
char_range_t *new_ranges = realloc(bracket->ranges, new_cap * sizeof(char_range_t));
|
|
if (!new_ranges) return false;
|
|
bracket->ranges = new_ranges;
|
|
bracket->capacity = new_cap;
|
|
return true;
|
|
}
|
|
|
|
void bracket_add_char(bracket_class_t *bracket, char c) {
|
|
bracket_add_range(bracket, c, c);
|
|
}
|
|
|
|
void bracket_add_range(bracket_class_t *bracket, char start, char end) {
|
|
if (bracket->count >= bracket->capacity) {
|
|
if (!bracket_grow(bracket)) return;
|
|
}
|
|
bracket->ranges[bracket->count].start = start;
|
|
bracket->ranges[bracket->count].end = end;
|
|
bracket->count++;
|
|
}
|
|
|
|
void bracket_free(bracket_class_t *bracket) {
|
|
if (!bracket) return;
|
|
free(bracket->ranges);
|
|
free(bracket);
|
|
}
|
|
|
|
bool bracket_matches(bracket_class_t *bracket, char c) {
|
|
bool found = false;
|
|
for (size_t i = 0; i < bracket->count; i++) {
|
|
if (c >= bracket->ranges[i].start && c <= bracket->ranges[i].end) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
return bracket->negated ? !found : found;
|
|
}
|