<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/subex/subexstate.go
diff options
context:
space:
mode:
Diffstat (limited to 'subex/subexstate.go')
-rw-r--r--subex/subexstate.go249
1 files changed, 149 insertions, 100 deletions
diff --git a/subex/subexstate.go b/subex/subexstate.go
index 0b21c93..4de8ae2 100644
--- a/subex/subexstate.go
+++ b/subex/subexstate.go
@@ -4,13 +4,24 @@ package subex
// e.g. Combine all of the copy states into a single type that has a filter function
import (
+ "fmt"
"main/walk"
+ "strings"
)
-// A state of execution for the transducer
type SubexState interface {
+}
+
+type SubexEpsilonState interface {
+ SubexState
+ epsilon(aux auxiliaryState) []SubexBranch
+}
+
+// A state of execution for the transducer
+type SubexEatState interface {
+ SubexState
// Eat a Atom and transition to any number of new states
- eat(aux auxiliaryState, char walk.Edible) []SubexBranch
+ eat(aux auxiliaryState, edible walk.Edible) []SubexBranch
// Find accepting states reachable through epsilon transitions and return their outputs
accepting(aux auxiliaryState) []OutputStack
}
@@ -19,13 +30,18 @@ type SubexState interface {
type SubexGroupState struct {
first, second SubexState
}
-func (state SubexGroupState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
- otherAux := aux.cloneStore()
- return append(state.first.eat(aux, char), state.second.eat(otherAux, char)...)
-}
-func (state SubexGroupState) accepting(aux auxiliaryState) []OutputStack {
+func (state SubexGroupState) epsilon(aux auxiliaryState) []SubexBranch {
otherAux := aux.cloneStore()
- return append(state.first.accepting(aux), state.second.accepting(otherAux)...)
+ return []SubexBranch {
+ {
+ state: state.first,
+ aux: aux,
+ },
+ {
+ state: state.second,
+ aux: otherAux,
+ },
+ }
}
type SubexCopyState struct {
@@ -39,7 +55,7 @@ func (state SubexCopyState) eat(aux auxiliaryState, edible walk.Edible) []SubexB
}
return []SubexBranch{{
state: state.next,
- aux: aux.topAppend(walk.ValueList{value}),
+ aux: aux.topAppend([]walk.Value{value}),
}}
}
func (state SubexCopyState) accepting(aux auxiliaryState) []OutputStack {
@@ -51,29 +67,32 @@ type SubexCopyRuneState struct {
filter runeFilter
}
func (state SubexCopyRuneState) eat(aux auxiliaryState, edible walk.Edible) []SubexBranch {
- r, isRune := edible.(walk.StringRuneAtom)
- if !isRune || !state.filter.runeFilter(r) {
+ r, isRune := edible.(walk.RuneEdible)
+ if !isRune || !state.filter.runeFilter(rune(r)) {
return nil
}
return []SubexBranch{{
state: state.next,
- aux: aux.topAppend(walk.RuneList{r}),
+ aux: aux.topAppendRune([]rune{rune(r)}),
}}
}
func (state SubexCopyRuneState) accepting(aux auxiliaryState) []OutputStack {
return nil
}
+func (state SubexCopyRuneState) String() string {
+ return fmt.Sprintf("SubexCopyRuneState[%v]", state.filter)
+}
// 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 SubexCaptureBeginState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
- return state.next.eat(aux.pushOutput(walk.ValueList{}), char)
-}
-func (state SubexCaptureBeginState) accepting(aux auxiliaryState) []OutputStack {
- return state.next.accepting(aux.pushOutput(walk.ValueList{}))
+func (state SubexCaptureBeginState) epsilon(aux auxiliaryState) []SubexBranch {
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.pushOutput(nil),
+ }}
}
func (state SubexCaptureBeginState) String() string {
return "CaptureBeginState"
@@ -82,24 +101,22 @@ func (state SubexCaptureBeginState) String() string {
type SubexCaptureRunesBeginState struct {
next SubexState
}
-func (state SubexCaptureRunesBeginState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
- return state.next.eat(aux.pushOutput(walk.RuneList{}), char)
-}
-func (state SubexCaptureRunesBeginState) accepting(aux auxiliaryState) []OutputStack {
- return state.next.accepting(aux.pushOutput(walk.RuneList{}))
+func (state SubexCaptureRunesBeginState) epsilon(aux auxiliaryState) []SubexBranch {
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.pushOutputRunes(nil),
+ }}
}
// Discard the top of the OutputStack
type SubexDiscardState struct {
next SubexState
}
-func (state SubexDiscardState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
- _, newAux := aux.popOutput()
- return state.next.eat(newAux, char)
-}
-func (state SubexDiscardState) accepting(aux auxiliaryState) []OutputStack {
- _, newAux := aux.popOutput()
- return state.next.accepting(newAux)
+func (state SubexDiscardState) epsilon(aux auxiliaryState) []SubexBranch {
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.popDiscardOutput(),
+ }}
}
// Pop the top of the OutputStack which contains the stuff outputted since the start of the store
@@ -108,17 +125,15 @@ type SubexStoreEndState struct {
slot int
next SubexState
}
-func (state SubexStoreEndState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
+func (state SubexStoreEndState) epsilon(aux auxiliaryState) []SubexBranch {
toStore, aux := aux.popOutput()
- aux = aux.withValue(state.slot, toStore)
- return state.next.eat(aux, char)
-}
-func (state SubexStoreEndState) accepting(aux auxiliaryState) []OutputStack {
- toStore, aux := aux.popOutput()
- aux = aux.withValue(state.slot, toStore)
- return state.next.accepting(aux)
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.withValue(state.slot, toStore),
+ }}
}
+/*
// A part of an output literal, either an Atom or a slot from which to load
type OutputContent interface {
// Given the current store, return the ValueList produced by the TransducerOutput
@@ -184,7 +199,7 @@ func (state SubexOutputState) build(store Store) walk.ValueList {
}
return result
}
-func (state SubexOutputState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
+func (state SubexOutputState) eat(aux auxiliaryState, char walk.Value) []SubexBranch {
content := state.build(aux.store)
nextStates := state.next.eat(aux.topAppend(content), char)
return nextStates
@@ -194,10 +209,55 @@ func (state SubexOutputState) accepting(aux auxiliaryState) []OutputStack {
outputStacks := state.next.accepting(aux.topAppend(content))
return outputStacks
}
+*/
+
+type OutputValue interface {
+ build(store Store) []walk.Value
+}
+
+type OutputValueLoad struct {
+ slot int
+}
+func (ov OutputValueLoad) build(store Store) []walk.Value {
+ return store.values[ov.slot]
+}
+
+type OutputValueLiteral struct {
+ scalar walk.Scalar
+}
+func (ov OutputValueLiteral) build(store Store) []walk.Value {
+ return []walk.Value{ov.scalar}
+}
+
+type SubexOutputValuesState struct {
+ content []OutputValue
+ next SubexState
+}
+func (state SubexOutputValuesState) epsilon(aux auxiliaryState) []SubexBranch {
+ var content []walk.Value
+ for _, el := range state.content {
+ content = append(content, el.build(aux.store)...)
+ }
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.topAppend(content),
+ }}
+}
+
+type OutputRune interface {
+}
+
+type OutputRuneLoad struct {
+ slot int
+}
+
+type OutputRuneLiteral struct {
+ r rune
+}
// A final state, transitions to nothing but is accepting
type SubexNoneState struct {}
-func (state SubexNoneState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
+func (state SubexNoneState) eat(aux auxiliaryState, edible walk.Edible) []SubexBranch {
return nil
}
func (state SubexNoneState) accepting(aux auxiliaryState) []OutputStack {
@@ -206,7 +266,7 @@ func (state SubexNoneState) accepting(aux auxiliaryState) []OutputStack {
// A dead end state, handy for making internals work nicer but technically redundant
type SubexDeadState struct {}
-func (state SubexDeadState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
+func (state SubexDeadState) eat(aux auxiliaryState, edible walk.Edible) []SubexBranch {
return nil
}
func (state SubexDeadState) accepting (aux auxiliaryState) []OutputStack {
@@ -239,31 +299,18 @@ func (state SubexDeadState) accepting (aux auxiliaryState) []OutputStack {
type SubexArithmeticEndState struct {
next SubexState
- calculate func(walk.ValueList) (walk.ValueList, error)
+ calculate func([]walk.Value) ([]walk.Value, error)
}
-func (state SubexArithmeticEndState) eat(aux auxiliaryState, char walk.Edible) []SubexBranch {
- toCompute, aux := aux.popOutput()
- values, isValues := toCompute.(walk.ValueList)
- if !isValues {
- panic("Tried to do arithmetic on non-values")
- }
- result, err := state.calculate(values)
- if err != nil {
- return nil
- }
- return state.next.eat(aux.topAppend(result), char)
-}
-func (state SubexArithmeticEndState) accepting(aux auxiliaryState) []OutputStack {
- toCompute, aux := aux.popOutput()
- values, isValues := toCompute.(walk.ValueList)
- if !isValues {
- panic("Tried to do arithmetic on non-values")
- }
+func (state SubexArithmeticEndState) epsilon(aux auxiliaryState) []SubexBranch {
+ values, aux := aux.popOutput()
result, err := state.calculate(values)
if err != nil {
return nil
}
- return state.next.accepting(aux.topAppend(result))
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.topAppend(result),
+ }}
}
type SubexDiscardTerminalState struct {
@@ -286,55 +333,57 @@ func (state SubexDiscardTerminalState) accepting(aux auxiliaryState) []OutputSta
type SubexConstructArrayState struct {
next SubexState
}
-func (state SubexConstructArrayState) eat(aux auxiliaryState, edible walk.Edible) []SubexBranch {
- outputs, aux := aux.popOutput()
- values, isValues := outputs.(walk.ValueList)
- if !isValues {
- panic("Tried to create an array from non-values")
+func (state SubexConstructArrayState) epsilon(aux auxiliaryState) []SubexBranch {
+ values, aux := aux.popOutput()
+ var array walk.ArrayValue
+ if len(values) % 2 != 0 {
+ panic("Tried to construct array with odd length input")
}
- array := walk.ArrayStructure(values)
- return state.next.eat(aux.topAppend(walk.ValueList{array}), edible)
-}
-func (state SubexConstructArrayState) accepting(aux auxiliaryState) []OutputStack {
- outputs, aux := aux.popOutput()
- values, isValues := outputs.(walk.ValueList)
- if !isValues {
- panic("Tried to create an array from non-values")
+ for i := 0; i < len(values); i += 2 {
+ index, isNum := values[i].(walk.NumberValue)
+ if !isNum {
+ panic("Tried to construct array with non-numeric index")
+ }
+ array = append(array, walk.ArrayElement {
+ Index: int(index),
+ Value: values[i + 1],
+ })
}
- array := walk.ArrayStructure(values)
- return state.next.accepting(aux.topAppend(walk.ValueList{array}))
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.topAppend([]walk.Value {array}),
+ }}
}
type SubexConstructStringState struct {
next SubexState
}
-func (state SubexConstructStringState) eat(aux auxiliaryState, edible walk.Edible) []SubexBranch {
- outputs, aux := aux.popOutput()
- runes, isRunes := outputs.(walk.RuneList)
- if !isRunes {
- panic("Tried to create a string from non-runes")
+func (state SubexConstructStringState) construct(runes []rune) []walk.Value {
+ var builder strings.Builder
+ for _, r := range runes {
+ builder.WriteRune(r)
}
- s := walk.StringStructure(runes)
- return state.next.eat(aux.topAppend(walk.ValueList{s}), edible)
+ return []walk.Value{walk.StringValue(builder.String())}
}
-func (state SubexConstructStringState) accepting(aux auxiliaryState) []OutputStack {
- outputs, aux := aux.popOutput()
- runes, isRunes := outputs.(walk.RuneList)
- if !isRunes {
- panic("Tried to create a string from non-runes")
- }
- s := walk.StringStructure(runes)
- return state.next.accepting(aux.topAppend(walk.ValueList{s}))
+func (state SubexConstructStringState) epsilon(aux auxiliaryState) []SubexBranch {
+ runes, aux := aux.popOutputRunes()
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.topAppend(state.construct(runes)),
+ }}
+}
+func (state SubexConstructStringState) String() string {
+ return "SubexConstructStringState"
}
type SubexIncrementNestState struct {
next SubexState
}
-func (state SubexIncrementNestState) eat(aux auxiliaryState, edible walk.Edible) []SubexBranch {
- return state.next.eat(aux.incNest(), edible)
-}
-func (state SubexIncrementNestState) accepting(aux auxiliaryState) []OutputStack {
- return state.next.accepting(aux.incNest())
+func (state SubexIncrementNestState) epsilon(aux auxiliaryState) []SubexBranch {
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.incNest(),
+ }}
}
func (state SubexIncrementNestState) String() string {
return "IncrementNestState"
@@ -343,9 +392,9 @@ func (state SubexIncrementNestState) String() string {
type SubexDecrementNestState struct {
next SubexState
}
-func (state SubexDecrementNestState) eat(aux auxiliaryState, edible walk.Edible) []SubexBranch {
- return state.next.eat(aux.decNest(), edible)
-}
-func (state SubexDecrementNestState) accepting(aux auxiliaryState) []OutputStack {
- return state.next.accepting(aux.decNest())
+func (state SubexDecrementNestState) epsilon(aux auxiliaryState) []SubexBranch {
+ return []SubexBranch {{
+ state: state.next,
+ aux: aux.decNest(),
+ }}
}