/* retoor */ #include "repl.h" #include "loreg.h" #include #include #include #define MAX_INPUT 4096 static void print_banner(void) { printf("loreg v%s - regex interpreter\n", LOREG_VERSION); printf("commands: :q quit, :h help, :p set pattern, :m match, :s search\n\n"); } static void print_help(void) { printf("loreg REPL commands:\n"); printf(" :q quit\n"); printf(" :h show this help\n"); printf(" :p compile and set pattern\n"); printf(" :m match text against pattern (anchored)\n"); printf(" :s search for pattern in text\n"); printf(" search for pattern in text\n\n"); printf("regex syntax:\n"); printf(" . any character\n"); printf(" * zero or more\n"); printf(" + one or more\n"); printf(" ? zero or one\n"); printf(" | alternation\n"); printf(" () grouping\n"); printf(" [] character class\n"); printf(" [^] negated class\n"); printf(" ^ start anchor\n"); printf(" $ end anchor\n"); printf(" {n} exactly n\n"); printf(" {n,} n or more\n"); printf(" {n,m} n to m\n"); printf(" \\d digit\n"); printf(" \\w word character\n"); printf(" \\s whitespace\n"); printf(" \\D \\W \\S negated classes\n\n"); } static void print_match(const char *text, loreg_match_t *result) { if (!result->matched) { printf("no match\n"); return; } printf("match: \""); for (size_t i = result->match_start; i < result->match_end; i++) { printf("%c", text[i]); } printf("\" [%zu-%zu]\n", result->match_start, result->match_end); for (size_t i = 0; i < result->group_count; i++) { if (result->groups[i].matched) { printf(" group %zu: \"", i); for (size_t j = result->groups[i].start; j < result->groups[i].end; j++) { printf("%c", text[j]); } printf("\" [%zu-%zu]\n", result->groups[i].start, result->groups[i].end); } } } static char *read_line(void) { static char buffer[MAX_INPUT]; printf("> "); fflush(stdout); if (!fgets(buffer, MAX_INPUT, stdin)) { return NULL; } size_t len = strlen(buffer); if (len > 0 && buffer[len - 1] == '\n') { buffer[len - 1] = '\0'; } return buffer; } void repl_run(void) { print_banner(); loreg_regex_t *regex = NULL; char *line; while ((line = read_line()) != NULL) { if (strlen(line) == 0) continue; if (strcmp(line, ":q") == 0 || strcmp(line, ":quit") == 0) { break; } if (strcmp(line, ":h") == 0 || strcmp(line, ":help") == 0) { print_help(); continue; } if (strncmp(line, ":p ", 3) == 0) { const char *pattern = line + 3; while (*pattern == ' ') pattern++; if (regex) { loreg_free(regex); regex = NULL; } loreg_error_t error; regex = loreg_compile(pattern, &error); if (!regex) { printf("error: %s\n", loreg_error_string(error)); } else { printf("pattern compiled: %s\n", pattern); } continue; } if (strncmp(line, ":m ", 3) == 0) { if (!regex) { printf("error: no pattern set (use :p )\n"); continue; } const char *text = line + 3; while (*text == ' ') text++; loreg_match_t result; loreg_match(regex, text, &result); print_match(text, &result); continue; } if (strncmp(line, ":s ", 3) == 0) { if (!regex) { printf("error: no pattern set (use :p )\n"); continue; } const char *text = line + 3; while (*text == ' ') text++; loreg_match_t result; loreg_search(regex, text, &result); print_match(text, &result); continue; } if (line[0] == ':') { printf("unknown command: %s\n", line); continue; } if (!regex) { printf("error: no pattern set (use :p )\n"); continue; } loreg_match_t result; loreg_search(regex, line, &result); print_match(line, &result); } if (regex) { loreg_free(regex); } printf("\n"); }