/* 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;
}