# loreg
retoor <retoor@molodetz.nl>
A high-performance regular expression interpreter implemented from scratch in plain C. The engine uses Thompson's NFA construction algorithm for efficient pattern matching.
## CI
The project includes Gitea Actions CI that runs on every push and pull request:
- Build verification (release and debug)
- Full test suite (569 tests)
- Valgrind memory leak detection
- Code coverage generation
## Features
- Full regex syntax support: literals, metacharacters, quantifiers, character classes, groups, alternation, anchors
- NFA-based matching engine with Thompson construction
- Capturing groups with match position tracking
- Interactive REPL for testing patterns
- Zero external dependencies
- Comprehensive test suite with 569 tests
- Memory-safe implementation verified with Valgrind
## Building
```sh
make # optimized release build
make debug # debug build with symbols
make test # run all tests
make coverage # generate coverage report
make profile # generate profiling report
make valgrind # run under valgrind
```
## Usage
### Command Line
```sh
./loreg "pattern" "text" # search for pattern in text
./loreg -m "pattern" "text" # full match mode
./loreg -i # start REPL
./loreg # start REPL (default)
```
### REPL Commands
```
:p <pattern> compile and set pattern
:m <text> match text (anchored)
:s <text> search for pattern in text
<text> search (default)
:h help
:q quit
```
### C API
```c
#include "loreg.h"
loreg_error_t err;
loreg_regex_t *re = loreg_compile("\\d{3}-\\d{4}", &err);
if (!re) {
fprintf(stderr, "error: %s\n", loreg_error_string(err));
return 1;
}
loreg_match_t result;
if (loreg_search(re, "call 555-1234 now", &result)) {
printf("match at [%zu-%zu]\n", result.match_start, result.match_end);
}
loreg_free(re);
```
## Supported Syntax
| Pattern | Description |
|---------|-------------|
| `.` | any character except newline |
| `*` | zero or more |
| `+` | one or more |
| `?` | zero or one |
| `\|` | alternation |
| `()` | grouping and capture |
| `[]` | character class |
| `[^]` | negated character class |
| `[a-z]` | character range |
| `^` | start anchor |
| `$` | end anchor |
| `{n}` | exactly n |
| `{n,}` | n or more |
| `{n,m}` | n to m |
| `\d` | digit [0-9] |
| `\w` | word [a-zA-Z0-9_] |
| `\s` | whitespace |
| `\D` | non-digit |
| `\W` | non-word |
| `\S` | non-whitespace |
| `*?` `+?` `??` | non-greedy quantifiers |
## Architecture
```
src/
├── lexer.c tokenizer for regex patterns
├── parser.c recursive descent parser producing AST
├── ast.c abstract syntax tree node types
├── nfa.c Thompson NFA construction
├── matcher.c NFA simulation with epsilon closure
├── loreg.c public API
├── repl.c interactive REPL
└── main.c CLI entry point
include/
├── loreg.h public header
├── lexer.h lexer interface
├── parser.h parser interface
├── ast.h AST types
├── nfa.h NFA types
├── matcher.h matcher interface
└── repl.h REPL interface
tests/
├── test_lexer.c lexer unit tests (10 tests)
├── test_parser.c parser unit tests (20 tests)
├── test_nfa.c NFA construction tests (14 tests)
├── test_matcher.c matching tests (27 tests)
├── test_all.c comprehensive tests (9 tests)
└── test_integration.c integration tests (489 tests)
```
## Test Suite
The test suite contains 569 tests covering:
| Category | Description |
|----------|-------------|
| Lexer | Tokenization of patterns |
| Parser | AST construction and error handling |
| NFA | State machine construction |
| Matcher | Pattern matching correctness |
| Integration | Real-world regex patterns |
Integration tests cover:
- Literal matching and concatenation
- Dot metacharacter and wildcards
- Start/end anchors
- All quantifiers (*, +, ?, {n,m})
- Alternation and grouping
- Character classes and ranges
- Negated character classes
- Escape sequences
- Email, IP, URL, phone patterns
- Greedy vs non-greedy matching
- Nested groups and complex nesting
- Edge cases and boundary conditions
- Pathological/stress patterns
Run tests with Valgrind verification:
```sh
make test # run all 569 tests
make valgrind # verify zero memory leaks
```
## Algorithm
The implementation uses Thompson's construction to convert regex patterns to NFAs:
1. **Lexer**: Tokenizes the pattern into a stream of tokens
2. **Parser**: Builds an AST using recursive descent parsing
3. **NFA Construction**: Converts AST to NFA using Thompson's algorithm
4. **Matching**: Simulates NFA with epsilon closure for linear-time matching
Time complexity: O(n*m) where n is pattern length and m is text length.
## License
MIT