diff options
author | Charlie Stanton <charlie@shtanton.xyz> | 2022-09-21 21:05:34 +0100 |
---|---|---|
committer | Charlie Stanton <charlie@shtanton.xyz> | 2022-09-21 21:05:34 +0100 |
commit | 0a8690993d572a50b95dd4f1c1903ed00ddb9c2b (patch) | |
tree | 2ab207544c88ff19308e22c8b79c3ea349c97faa /main/subexast.go | |
download | subex-0a8690993d572a50b95dd4f1c1903ed00ddb9c2b.tar |
Initial commit
Parses and executes substitute expressions (subexes)
So far subex has the following operations:
- Concatenation of a and b with ab
- Or with |
- Repeat maximally with *
- Repeat minimally with -
- Copy a specific character 'a'
- Copy any character '.'
- Store text matching a regex into slot 's': `$s(regex)`
- Output text in "" including loading from slots with '$'
Regexes support all the same operations as subexes minus storing and outputting
This first implementation gives very little thought to efficiency
Example:
./main 'according to all known laws of aviation' '$1(.-)$m(( .* )| ).*"$m$1"'
This swaps the first and last words of the input string
Diffstat (limited to 'main/subexast.go')
-rw-r--r-- | main/subexast.go | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/main/subexast.go b/main/subexast.go new file mode 100644 index 0000000..7e2f33c --- /dev/null +++ b/main/subexast.go @@ -0,0 +1,117 @@ +package main + +import ( + "fmt" +) + +type SubexAST interface { + compileWith(next SubexState) SubexState +} + +type SubexASTConcat struct { + first, second SubexAST +} +func (ast SubexASTConcat) compileWith(next SubexState) SubexState { + return ast.first.compileWith(ast.second.compileWith(next)) +} +func (ast SubexASTConcat) String() string { + return fmt.Sprintf("(%v)(%v)", ast.first, ast.second) +} + +type SubexASTStore struct { + match RegexAST + slot rune +} +func (ast SubexASTStore) compileWith(next SubexState) SubexState { + return SubexStoreState { + match: ast.match.compileWith(RegexNoneState{}), + slot: ast.slot, + next: next, + } +} +func (ast SubexASTStore) String() string { + return fmt.Sprintf("$%c(%v)", ast.slot, ast.match) +} + +type SubexASTOr struct { + first, second SubexAST +} +func (ast SubexASTOr) compileWith(next SubexState) SubexState { + return SubexGroupState { + ast.first.compileWith(next), + ast.second.compileWith(next), + } +} + +type SubexASTMaximise struct { + content SubexAST +} +func (ast SubexASTMaximise) compileWith(next SubexState) SubexState { + state := &SubexGroupState { + nil, + next, + } + state.first = ast.content.compileWith(state) + return state +} +func (ast SubexASTMaximise) String() string { + return fmt.Sprintf("(%v)*", ast.content) +} + +type SubexASTMinimise struct { + content SubexAST +} +func (ast SubexASTMinimise) compileWith(next SubexState) SubexState { + state := &SubexGroupState { + next, + nil, + } + state.second = ast.content.compileWith(state) + return state +} +func (ast SubexASTMinimise) String() string { + return fmt.Sprintf("(%v)-", ast.content) +} + +type SubexASTRepeat struct { + content SubexAST + min, max int +} +func (ast SubexASTRepeat) compileWith(next SubexState) SubexState { + for i := ast.min; i < ast.max; i += 1 { + next = SubexGroupState { + ast.content.compileWith(next), + next, + } + } + for i := 0; i < ast.min; i += 1 { + next = ast.content.compileWith(next) + } + return next +} + +type SubexASTCopyRune rune +func (ast SubexASTCopyRune) compileWith(next SubexState) SubexState { + return SubexCopyRuneState{ + rune: rune(ast), + next: next, + } +} + +type SubexASTCopyAny struct {} +func (ast SubexASTCopyAny) compileWith(next SubexState) SubexState { + return SubexCopyAnyState{next} +} +func (ast SubexASTCopyAny) String() string { + return "." +} + +type SubexASTOutput struct { + replacement []TransducerOutput +} +func (ast SubexASTOutput) compileWith(next SubexState) SubexState { + return SubexOutputState{ + content: ast.replacement, + next: next, + } +} |