From fb1f51d1da22f34509cf3fe1d174296d36a0f0ad Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Thu, 22 Dec 2022 15:23:28 +0000 Subject: Expressions inside stores are now subexes instead of regexes This simplifies things by no longer needing a regex implementation It also enables transforming text as it is being read into a slot --- main/main.go | 5 +++++ main/parse.go | 2 +- main/subexast.go | 4 ++-- main/subexstate.go | 32 +++++++++++++++++--------------- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/main/main.go b/main/main.go index be43d90..0466371 100644 --- a/main/main.go +++ b/main/main.go @@ -27,6 +27,11 @@ func (store Store) clone() Store { } 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{}) diff --git a/main/parse.go b/main/parse.go index 6cc20ea..18941f2 100644 --- a/main/parse.go +++ b/main/parse.go @@ -91,7 +91,7 @@ func parseSubex(l *RuneReader, minPower int) SubexAST { if slot == eof { panic("Missing slot character") } - match := parseRegex(l, 100) + match := parseSubex(l, 100) if match == nil { panic("Missing regex for store") } diff --git a/main/subexast.go b/main/subexast.go index 54cc5fe..510335f 100644 --- a/main/subexast.go +++ b/main/subexast.go @@ -19,12 +19,12 @@ func (ast SubexASTConcat) String() string { } type SubexASTStore struct { - match RegexAST + match SubexAST slot rune } func (ast SubexASTStore) compileWith(next SubexState) SubexState { return SubexStoreState { - match: ast.match.compileWith(RegexNoneState{}), + match: ast.match.compileWith(SubexNoneState{}), slot: ast.slot, next: next, } diff --git a/main/subexstate.go b/main/subexstate.go index cc697f0..00b9e75 100644 --- a/main/subexstate.go +++ b/main/subexstate.go @@ -21,25 +21,25 @@ func (state SubexGroupState) accepting(store Store) []string { } type SubexStoreState struct { - match RegexState + match SubexState slot rune next SubexState - input string + toStore 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) +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)...) } - nextRegexStates := state.match.eat(char) - for _, regexState := range nextRegexStates { + nextMatchStates := state.match.eat(store.clone(), char) + for _, matchState := range nextMatchStates { nextStates = append(nextStates, SubexBranch { state: SubexStoreState { - match: regexState, + match: matchState.state, slot: state.slot, next: state.next, - input: state.input + string(char), + toStore: state.toStore + matchState.output, }, output: "", store: store.clone(), @@ -47,11 +47,13 @@ func (state SubexStoreState) eat(store Store, char rune) []SubexBranch { } return nextStates } -func (state SubexStoreState) accepting(store Store) []string { - if state.match.accepting() { - return state.next.accepting(store) +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 nil + return outputs } type SubexOutputState struct { -- cgit v1.2.3