<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex/subexstate.go
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-04-18 15:07:52 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2023-04-18 15:07:52 +0100
commitffd1b73b4f3294d9f3aa2ed600da3ba053aeb47c (patch)
treeac3075e8ea26190838e0e6df3f5e6af65909ca51 /subex/subexstate.go
parentfebdc5dcd5b25a090b90c920914775265da98d39 (diff)
downloadstred-go-ffd1b73b4f3294d9f3aa2ed600da3ba053aeb47c.tar
Adds the sum operator
Currently doesn't parse strings as each atom is considered independantly. Instead individual characters in strings can be cast
Diffstat (limited to 'subex/subexstate.go')
-rw-r--r--subex/subexstate.go62
1 files changed, 62 insertions, 0 deletions
diff --git a/subex/subexstate.go b/subex/subexstate.go
index 3c554a2..cbcd210 100644
--- a/subex/subexstate.go
+++ b/subex/subexstate.go
@@ -188,3 +188,65 @@ func (state SubexRangeState) eat(store Store, char walk.Atom) []SubexBranch {
func (state SubexRangeState) accepting(store Store) [][]walk.Atom {
return nil
}
+
+func sumValues(values []walk.Atom) walk.ValueNumber {
+ var sum float64 = 0
+ for _, value := range values {
+ switch v := value.(type) {
+ case walk.ValueBool:
+ if (bool(v)) {
+ sum += 1
+ }
+ case walk.ValueNumber:
+ sum += float64(v)
+ case rune:
+ if '0' <= v && v <= '9' {
+ sum += float64(v - '0')
+ }
+ default:
+ }
+ }
+ return walk.ValueNumber(sum)
+}
+
+// Run the inputState machine and sum any values output, output the sum
+// Cast non numbers into numbers, ignore anything uncastable
+type SubexSumState struct {
+ inputState SubexState
+ next SubexState
+ sum walk.ValueNumber
+}
+func (state SubexSumState) eat(store Store, char walk.Atom) (nextStates []SubexBranch) {
+ acceptedOutputs := state.inputState.accepting(store)
+ for _, acceptedOutput := range acceptedOutputs {
+ nextNextStates := state.next.eat(store.clone(), char)
+ for i := range nextNextStates {
+ nextNextStates[i].output = walk.ConcatData([]walk.Atom{sumValues(append(acceptedOutput, state.sum))}, nextNextStates[i].output)
+ }
+ nextStates = append(nextStates, nextNextStates...)
+ }
+ nextInputStates := state.inputState.eat(store.clone(), char)
+ for _, inputState := range nextInputStates {
+ nextStates = append(nextStates, SubexBranch {
+ state: &SubexSumState {
+ inputState: inputState.state,
+ next: state.next,
+ sum: sumValues(append(inputState.output, state.sum)),
+ },
+ output: nil,
+ store: inputState.store,
+ })
+ }
+ return nextStates
+}
+func (state SubexSumState) accepting(store Store) (outputs [][]walk.Atom) {
+ acceptedOutputs := state.inputState.accepting(store)
+ for _, acceptedOutput := range acceptedOutputs {
+ nextOutputs := state.next.accepting(store.clone())
+ for i := range nextOutputs {
+ nextOutputs[i] = walk.ConcatData([]walk.Atom{sumValues(append(acceptedOutput, state.sum))}, nextOutputs[i])
+ }
+ outputs = append(outputs, nextOutputs...)
+ }
+ return outputs
+}