<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex/subexstate.go
diff options
context:
space:
mode:
authorCharlie Stanton <charlie@shtanton.xyz>2023-04-19 12:59:22 +0100
committerCharlie Stanton <charlie@shtanton.xyz>2023-04-19 12:59:22 +0100
commit0072e6aad2f9969348d5315a692f1f5e2ebc075d (patch)
tree0c75e9466a688694383279f56d69a46f014e3680 /subex/subexstate.go
parent053a403a77e5b4c46e82932e94d5fb7a4117ce43 (diff)
downloadstred-go-0072e6aad2f9969348d5315a692f1f5e2ebc075d.tar
Adds product/and operator
Diffstat (limited to 'subex/subexstate.go')
-rw-r--r--subex/subexstate.go87
1 files changed, 69 insertions, 18 deletions
diff --git a/subex/subexstate.go b/subex/subexstate.go
index 0a4f1bb..6a80eff 100644
--- a/subex/subexstate.go
+++ b/subex/subexstate.go
@@ -26,15 +26,15 @@ func (state SubexGroupState) accepting(store Store, outputStack OutputStack) []O
return append(state.first.accepting(store, outputStack), state.second.accepting(store, outputStack)...)
}
-// Push an empty value onto the OutputStack and epsilon transition to next
-// This value will be added to until SubexStoreEndState is reached when it will be stored
-type SubexStoreBeginState struct {
+// Just pushes to the OutputStack and hands over to the next state
+// Used to capture the output of the state being handed over to
+type SubexCaptureBeginState struct {
next SubexState
}
-func (state SubexStoreBeginState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch {
+func (state SubexCaptureBeginState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch {
return state.next.eat(store, outputStack.push(nil), char)
}
-func (state SubexStoreBeginState) accepting(store Store, outputStack OutputStack) []OutputStack {
+func (state SubexCaptureBeginState) accepting(store Store, outputStack OutputStack) []OutputStack {
return state.next.accepting(store, outputStack.push(nil))
}
@@ -187,7 +187,7 @@ func sumValues(atoms []walk.Atom) (walk.WalkValue, error) {
case walk.ValueNull:
allBools = false
case walk.ValueBool:
- if (bool(v)) {
+ if bool(v) {
sum += 1
any = true
}
@@ -213,19 +213,8 @@ func sumValues(atoms []walk.Atom) (walk.WalkValue, error) {
}
}
-// At the start of a sum, just pushes to the OutputStack allowing the end to capture what was output in the middle
-// Tries to cast values to numbers to sum them and rejects if values are not castable
-type SubexSumBeginState struct {
- next SubexState
-}
-func (state SubexSumBeginState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch {
- return state.next.eat(store, outputStack.push(nil), char)
-}
-func (state SubexSumBeginState) accepting(store Store, outputStack OutputStack) []OutputStack {
- return state.next.accepting(store, outputStack.push(nil))
-}
-
// At the end of a sum, pops what has been output since the start, sums and outputs it
+// If all values are booleans does OR, if not tries to cast values to numbers to sum them and rejects if values are not castable
type SubexSumEndState struct {
next SubexState
}
@@ -245,3 +234,65 @@ func (state SubexSumEndState) accepting(store Store, outputStack OutputStack) []
}
return state.next.accepting(store, topAppend(newStack, []walk.Atom{sum}))
}
+
+// Compounds atoms into values, if all values are booleans, does AND, if not, tries to cast to numbers and multiply
+func multiplyValues(atoms []walk.Atom) (walk.WalkValue, error) {
+ allBools := true
+ var product float64 = 1
+ var all bool = false
+ values, err := walk.MemoryCompound(atoms)
+ if err != nil {
+ return walk.ValueNull{}, err
+ }
+ for _, value := range values {
+ switch v := value.(type) {
+ case walk.ValueNull:
+ allBools = false
+ product *= 0
+ case walk.ValueBool:
+ if !bool(v) {
+ product *= 0
+ all = false
+ }
+ case walk.ValueNumber:
+ allBools = false
+ product *= float64(v)
+ case walk.ValueString:
+ allBools = false
+ num, err := strconv.ParseFloat(string(v), 64)
+ if err == nil {
+ product *= num
+ } else {
+ return walk.ValueNull{}, errors.New("Tried to sum non-castable string")
+ }
+ default:
+ return walk.ValueNull{}, errors.New("Tried to sum non-number")
+ }
+ }
+ if allBools {
+ return walk.ValueBool(all), nil
+ } else {
+ return walk.ValueNumber(product), nil
+ }
+}
+
+// Does AND or product
+type SubexProductEndState struct {
+ next SubexState
+}
+func (state SubexProductEndState) eat(store Store, outputStack OutputStack, char walk.Atom) []SubexBranch {
+ toMultiply, newStack := outputStack.pop()
+ product, err := multiplyValues(toMultiply)
+ if err != nil {
+ return nil
+ }
+ return state.next.eat(store, topAppend(newStack, []walk.Atom{product}), char)
+}
+func (state SubexProductEndState) accepting(store Store, outputStack OutputStack) []OutputStack {
+ toMultiply, newStack := outputStack.pop()
+ product, err := multiplyValues(toMultiply)
+ if err != nil {
+ return nil
+ }
+ return state.next.accepting(store, topAppend(newStack, []walk.Atom{product}))
+}