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) +}  | 
