|
/* retoor <retoor@molodetz.nl> */
|
|
#include "repl.h"
|
|
#include "lorex.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define MAX_INPUT 4096
|
|
|
|
static void print_banner(void) {
|
|
printf("lorex v%s - regex interpreter\n", LOREX_VERSION);
|
|
printf("commands: :q quit, :h help, :p <pattern> set pattern, :m <text> match, :s <text> search\n\n");
|
|
}
|
|
|
|
static void print_help(void) {
|
|
printf("lorex REPL commands:\n");
|
|
printf(" :q quit\n");
|
|
printf(" :h show this help\n");
|
|
printf(" :p <regex> compile and set pattern\n");
|
|
printf(" :m <text> match text against pattern (anchored)\n");
|
|
printf(" :s <text> search for pattern in text\n");
|
|
printf(" <text> 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, lorex_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();
|
|
|
|
lorex_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) {
|
|
lorex_free(regex);
|
|
regex = NULL;
|
|
}
|
|
|
|
lorex_error_t error;
|
|
regex = lorex_compile(pattern, &error);
|
|
if (!regex) {
|
|
printf("error: %s\n", lorex_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 <pattern>)\n");
|
|
continue;
|
|
}
|
|
|
|
const char *text = line + 3;
|
|
while (*text == ' ') text++;
|
|
|
|
lorex_match_t result;
|
|
lorex_match(regex, text, &result);
|
|
print_match(text, &result);
|
|
continue;
|
|
}
|
|
|
|
if (strncmp(line, ":s ", 3) == 0) {
|
|
if (!regex) {
|
|
printf("error: no pattern set (use :p <pattern>)\n");
|
|
continue;
|
|
}
|
|
|
|
const char *text = line + 3;
|
|
while (*text == ' ') text++;
|
|
|
|
lorex_match_t result;
|
|
lorex_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 <pattern>)\n");
|
|
continue;
|
|
}
|
|
|
|
lorex_match_t result;
|
|
lorex_search(regex, line, &result);
|
|
print_match(line, &result);
|
|
}
|
|
|
|
if (regex) {
|
|
lorex_free(regex);
|
|
}
|
|
|
|
printf("\n");
|
|
}
|