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/main.go | |
parent | 3636825c64bb6c172b0858d7a08c30acfcd68bdd (diff) | |
download | stred-go-fba426b3910f16c8abc6f819da3138f03e5f0b1a.tar |
Introduces subex processing
Doesn't integrate it at all yet
Diffstat (limited to 'subex/main.go')
-rw-r--r-- | subex/main.go | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/subex/main.go b/subex/main.go new file mode 100644 index 0000000..3ae0618 --- /dev/null +++ b/subex/main.go @@ -0,0 +1,114 @@ +package subex + +import ( + "os" + "fmt" + "io" +) + +type TransducerOutput interface { + build(Store) string +} + +type TransducerReplacementRune rune +func (replacement TransducerReplacementRune) build(store Store) string { + return string(replacement) +} + +type TransducerReplacementLoad rune +func (replacement TransducerReplacementLoad) build(store Store) string { + return store[rune(replacement)] +} + +type Store map[rune]string +func (store Store) clone() Store { + newStore := make(Store) + for key, val := range store { + newStore[key] = val + } + return newStore +} +func (store Store) withValue(key rune, value string) Store { + newStore := store.clone() + newStore[key] = value + return newStore +} + +func CompileTransducer(transducerAst SubexAST) SubexState { + return transducerAst.compileWith(SubexNoneState{}) +} + +type SubexBranch struct { + store Store + state SubexState + output string +} +func (pair SubexBranch) eat(char rune) []SubexBranch { + states := pair.state.eat(pair.store, char) + for i := range states { + states[i].output = pair.output + states[i].output + } + return states +} +func (pair SubexBranch) accepting() []string { + return pair.state.accepting(pair.store) +} + +func equalStates(left SubexBranch, right SubexBranch) bool { + // Only care about if they are the same pointer + return left.state == right.state +} + +func pruneStates(states []SubexBranch) (newStates []SubexBranch) { + outer: for _, state := range states { + for _, newState := range newStates { + if equalStates(state, newState) { + continue outer + } + } + newStates = append(newStates, state) + } + return newStates +} + +func RunTransducer(transducer SubexState, input string) (output string, err bool) { + states := []SubexBranch{{ + state: transducer, + output: "", + store: make(Store), + }} + for _, char := range input { + fmt.Printf("Running with %d states\n", len(states)) + var newStates []SubexBranch + for _, state := range states { + newStates = append(newStates, state.eat(char)...) + } + states = pruneStates(newStates) + } + for _, state := range states { + outputEnds := state.accepting() + for _, outputEnd := range outputEnds { + return state.output + outputEnd, false + } + } + return "", true +} + +func Main() { + if len(os.Args) != 2 { + panic("Expected: program [subex]") + } + inputBytes, inputErr := io.ReadAll(os.Stdin) + input := string(inputBytes) + if inputErr != nil { + fmt.Println("Error reading") + } + program := os.Args[1] + ast := Parse(program) + transducer := CompileTransducer(ast) + output, err := RunTransducer(transducer, input) + if err { + output = input + } + fmt.Print(output) +} |