<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex/subexstate.go
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-02-19 08:59:16 +0000
committerCharlie Stanton <charlie@shtanton.xyz>2023-02-19 08:59:16 +0000
commitfba426b3910f16c8abc6f819da3138f03e5f0b1a (patch)
tree9ce7473194a7ac4d97278cff3e95e58fd3277c72 /subex/subexstate.go
parent3636825c64bb6c172b0858d7a08c30acfcd68bdd (diff)
downloadstred-go-fba426b3910f16c8abc6f819da3138f03e5f0b1a.tar
Introduces subex processing
Doesn't integrate it at all yet
Diffstat (limited to 'subex/subexstate.go')
-rw-r--r--subex/subexstate.go145
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
+}