From ffd1b73b4f3294d9f3aa2ed600da3ba053aeb47c Mon Sep 17 00:00:00 2001 From: Charlie Stanton Date: Tue, 18 Apr 2023 15:07:52 +0100 Subject: Adds the sum operator Currently doesn't parse strings as each atom is considered independantly. Instead individual characters in strings can be cast --- subex/subexstate.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'subex/subexstate.go') 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 +} -- cgit v1.2.3