From 0a8690993d572a50b95dd4f1c1903ed00ddb9c2b Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Wed, 21 Sep 2022 21:05:34 +0100 Subject: 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 --- main/subexstate.go | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 main/subexstate.go (limited to 'main/subexstate.go') diff --git a/main/subexstate.go b/main/subexstate.go new file mode 100644 index 0000000..cc697f0 --- /dev/null +++ b/main/subexstate.go @@ -0,0 +1,123 @@ +package main + +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 RegexState + slot rune + next SubexState + input string +} +func (state SubexStoreState) eat(store Store, char rune) []SubexBranch { + var nextStates []SubexBranch + if state.match.accepting() { + store[state.slot] = state.input + nextStates = state.next.eat(store, char) + } + nextRegexStates := state.match.eat(char) + for _, regexState := range nextRegexStates { + nextStates = append(nextStates, SubexBranch { + state: SubexStoreState { + match: regexState, + slot: state.slot, + next: state.next, + input: state.input + string(char), + }, + output: "", + store: store.clone(), + }) + } + return nextStates +} +func (state SubexStoreState) accepting(store Store) []string { + if state.match.accepting() { + return state.next.accepting(store) + } + return nil +} + +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 +} -- cgit v1.2.3