diff options
author | Charlie Stanton <charlie@shtanton.xyz> | 2023-02-19 08:59:16 +0000 |
---|---|---|
committer | Charlie Stanton <charlie@shtanton.xyz> | 2023-02-19 08:59:16 +0000 |
commit | fba426b3910f16c8abc6f819da3138f03e5f0b1a (patch) | |
tree | 9ce7473194a7ac4d97278cff3e95e58fd3277c72 /subex/subexstate.go | |
parent | 3636825c64bb6c172b0858d7a08c30acfcd68bdd (diff) | |
download | stred-go-fba426b3910f16c8abc6f819da3138f03e5f0b1a.tar |
Introduces subex processing
Doesn't integrate it at all yet
Diffstat (limited to 'subex/subexstate.go')
-rw-r--r-- | subex/subexstate.go | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/subex/subexstate.go b/subex/subexstate.go new file mode 100644 index 0000000..2e613e8 --- /dev/null +++ b/subex/subexstate.go @@ -0,0 +1,145 @@ +package subex + +import ( + "strings" +) + +type SubexState interface { + eat(store Store, char rune) []SubexBranch + accepting(store Store) []string +} + +type SubexGroupState struct { + first, second SubexState +} +func (state SubexGroupState) eat(store Store, char rune) []SubexBranch { + otherStore := store.clone() + return append(state.first.eat(store, char), state.second.eat(otherStore, char)...) +} +func (state SubexGroupState) accepting(store Store) []string { + return append(state.first.accepting(store), state.second.accepting(store)...) +} + +type SubexStoreState struct { + match SubexState + slot rune + next SubexState + toStore string +} +func (state SubexStoreState) eat(store Store, char rune) (nextStates []SubexBranch) { + acceptedOutputs := state.match.accepting(store) + for _, acceptedOutput := range acceptedOutputs { + nextStore := store.withValue(state.slot, state.toStore + acceptedOutput) + nextStates = append(nextStates, state.next.eat(nextStore.clone(), char)...) + } + nextMatchStates := state.match.eat(store.clone(), char) + for _, matchState := range nextMatchStates { + nextStates = append(nextStates, SubexBranch { + state: SubexStoreState { + match: matchState.state, + slot: state.slot, + next: state.next, + toStore: state.toStore + matchState.output, + }, + output: "", + store: store.clone(), + }) + } + return nextStates +} +func (state SubexStoreState) accepting(store Store) (outputs []string) { + acceptedOutputs := state.match.accepting(store) + for _, acceptedOutput := range acceptedOutputs { + nextStore := store.withValue(state.slot, state.toStore + acceptedOutput) + outputs = append(outputs, state.next.accepting(nextStore)...) + } + return outputs +} + +type SubexOutputState struct { + content []TransducerOutput + next SubexState +} +func (state SubexOutputState) build(store Store) string { + var builder strings.Builder + for _, part := range state.content { + builder.WriteString(part.build(store)) + } + return builder.String() +} +func (state SubexOutputState) eat(store Store, char rune) []SubexBranch { + content := state.build(store) + nextStates := state.next.eat(store, char) + for i := range nextStates { + nextStates[i].output = content + nextStates[i].output + } + return nextStates +} +func (state SubexOutputState) accepting(store Store) []string { + content := state.build(store) + outputs := state.next.accepting(store) + for i := range outputs { + outputs[i] = content + outputs[i] + } + return outputs +} + +type SubexNoneState struct {} +func (state SubexNoneState) eat(store Store, char rune) []SubexBranch { + return nil +} +func (state SubexNoneState) accepting(store Store) []string { + return []string{""} +} + +type SubexCopyRuneState struct { + rune rune + next SubexState +} +func (state SubexCopyRuneState) eat(store Store, char rune) []SubexBranch { + if char == state.rune { + return []SubexBranch{{ + state: state.next, + output: string(char), + store: store, + }} + } + return nil +} +func (state SubexCopyRuneState) accepting(store Store) []string { + return nil +} + +type SubexCopyAnyState struct { + next SubexState +} +func (state SubexCopyAnyState) eat(store Store, char rune) []SubexBranch { + return []SubexBranch{{ + state: state.next, + output: string(char), + store: store, + }} +} +func (state SubexCopyAnyState) accepting(store Store) []string { + return nil +} + +type SubexRangeState struct { + parts map[rune]rune + next SubexState +} +func (state SubexRangeState) eat(store Store, char rune) []SubexBranch { + out, exists := state.parts[char] + if !exists { + return nil + } else { + return []SubexBranch{{ + state: state.next, + output: string(out), + store: store, + }} + } +} +func (state SubexRangeState) accepting(store Store) []string { + return nil +} |