<- Back to shtanton's homepage
aboutsummaryrefslogtreecommitdiff
path: root/walk/walk.go
diff options
context:
space:
mode:
Diffstat (limited to 'walk/walk.go')
-rw-r--r--walk/walk.go259
1 files changed, 246 insertions, 13 deletions
diff --git a/walk/walk.go b/walk/walk.go
index 1073c67..65fac6e 100644
--- a/walk/walk.go
+++ b/walk/walk.go
@@ -1,17 +1,232 @@
package walk
import (
- "strings"
+ "fmt"
"math"
+ "strings"
"unicode/utf8"
)
+type valueIter struct {
+ values []Value
+ index int
+}
+func (iter *valueIter) Next() Edible {
+ if iter.index >= len(iter.values) {
+ return nil
+ }
+ iter.index += 1
+ return iter.values[iter.index - 1]
+}
+
+func NewValueIter(values []Value) StructureIter {
+ return &valueIter {
+ values: values,
+ index: 0,
+ }
+}
+
+type OutputList interface {
+ outputList()
+}
+
+type StructureIter interface {
+ Next() Edible
+}
+
+type Edible interface {
+ edible()
+}
+
+type Atom interface {
+ Edible
+ atom()
+}
+
+type Scalar interface {
+ Atom
+ Value
+}
+
+type Structure interface {
+ Value
+ structure()
+ Iter() StructureIter
+}
+
+type Value interface {
+ Edible
+ value()
+ Debug() string
+}
+
+type Terminal interface {
+ Atom
+ terminal()
+}
+
+type ValueList []Value
+func (_ ValueList) outputList() {}
+
+type RuneList []StringRuneAtom
+func (_ RuneList) outputList() {}
+
+type NullScalar struct{}
+func (_ NullScalar) edible() {}
+func (_ NullScalar) atom() {}
+func (_ NullScalar) value() {}
+func (_ NullScalar) Debug() string {
+ return "null"
+}
+
+type BoolScalar bool
+func (_ BoolScalar) edible() {}
+func (_ BoolScalar) atom() {}
+func (_ BoolScalar) value() {}
+func (b BoolScalar) Debug() string {
+ if b {
+ return "true"
+ }
+ return "false"
+}
+
+type NumberScalar float64
+func (_ NumberScalar) edible() {}
+func (_ NumberScalar) atom() {}
+func (_ NumberScalar) value() {}
+func (n NumberScalar) Debug() string {
+ return fmt.Sprintf("%v", float64(n))
+}
+
+type StringStructure string
+func (_ StringStructure) edible() {}
+func (_ StringStructure) value() {}
+func (_ StringStructure) structure() {}
+func (s StringStructure) Iter() StructureIter {
+ return &stringStructureIter {
+ string: string(s),
+ position: 0,
+ }
+}
+func (s StringStructure) Debug() string {
+ return fmt.Sprintf("%q", string(s))
+}
+
+type stringStructureIter struct {
+ string string
+ position int
+}
+func (iter *stringStructureIter) Next() Edible {
+ if iter.position == -1 {
+ return nil
+ }
+ r, width := utf8.DecodeRuneInString(iter.string[iter.position:])
+ if width == 0 {
+ iter.position = -1
+ return StringEndTerminal{}
+ }
+ iter.position += width
+ return StringRuneAtom(r)
+}
+
+type StringBeginTerminal struct{}
+func (_ StringBeginTerminal) edible() {}
+func (_ StringBeginTerminal) atom() {}
+func (_ StringBeginTerminal) terminal() {}
+
+type StringEndTerminal struct{}
+func (_ StringEndTerminal) edible() {}
+func (_ StringEndTerminal) atom() {}
+func (_ StringEndTerminal) terminal() {}
+
+type StringRuneAtom rune
+func (_ StringRuneAtom) edible() {}
+func (_ StringRuneAtom) atom() {}
+
+type ArrayStructure []Value
+func (_ ArrayStructure) edible() {}
+func (_ ArrayStructure) value() {}
+func (_ ArrayStructure) structure() {}
+func (array ArrayStructure) Iter() StructureIter {
+ return &arrayStructureIter {
+ array: []Value(array),
+ index: 0,
+ }
+}
+func (array ArrayStructure) Debug() string {
+ builder := strings.Builder{}
+ builder.WriteRune('[')
+ var sep string
+ for _, element := range array {
+ builder.WriteString(sep)
+ builder.WriteString(fmt.Sprintf("%v", element))
+ sep = ", "
+ }
+ builder.WriteRune(']')
+ return builder.String()
+}
+
+type arrayStructureIter struct {
+ array []Value
+ index int
+}
+func (iter *arrayStructureIter) Next() Edible {
+ if iter.index > len(iter.array) {
+ return nil
+ }
+ if iter.index == len(iter.array) {
+ iter.index += 1
+ return ArrayEndTerminal{}
+ }
+ iter.index += 1
+ return iter.array[iter.index - 1]
+}
+
+type ArrayBeginTerminal struct{}
+func (_ ArrayBeginTerminal) edible() {}
+func (_ ArrayBeginTerminal) atom() {}
+func (_ ArrayBeginTerminal) terminal() {}
+
+type ArrayEndTerminal struct{}
+func (_ ArrayEndTerminal) edible() {}
+func (_ ArrayEndTerminal) atom() {}
+func (_ ArrayEndTerminal) terminal() {}
+
+type MapStructure map[string]Value
+func (_ MapStructure) edible() {}
+func (_ MapStructure) value() {}
+func (_ MapStructure) structure() {}
+func (m MapStructure) Debug() string {
+ builder := strings.Builder{}
+ builder.WriteRune('{')
+ var sep string
+ for key, value := range m {
+ builder.WriteString(sep)
+ builder.WriteString(fmt.Sprintf("%q", key))
+ builder.WriteString(": ")
+ builder.WriteString(fmt.Sprintf("%q", value))
+ sep = ", "
+ }
+ builder.WriteRune('}')
+ return builder.String()
+}
+
+type MapBeginTerminal struct{}
+func (_ MapBeginTerminal) edible() {}
+func (_ MapBeginTerminal) atom() {}
+func (_ MapBeginTerminal) terminal() {}
+
+type MapEndTerminal struct{}
+func (_ MapEndTerminal) edible() {}
+func (_ MapEndTerminal) atom() {}
+func (_ MapEndTerminal) terminal() {}
+
// int or string
type PathSegment interface {}
type Path []PathSegment
-func (path Path) ToWalkValues() []Value {
- var values []Value
+func (path Path) ToWalkValues() []ValueOLD {
+ var values []ValueOLD
for _, segment := range path {
switch s := segment.(type) {
case int:
@@ -25,7 +240,7 @@ func (path Path) ToWalkValues() []Value {
return values
}
-func PathFromWalkValues(values []Value) Path {
+func PathFromWalkValues(values []ValueOLD) Path {
var segments []PathSegment
for _, value := range values {
switch v := value.(type) {
@@ -41,18 +256,36 @@ func PathFromWalkValues(values []Value) Path {
}
type WalkItem struct {
- Value []Atom
- Path []Atom
+ Value ValueList
+ Path ValueList
+}
+
+func (item WalkItem) Debug() string {
+ builder := strings.Builder{}
+ var sep string
+ for _, pathSegment := range item.Path {
+ builder.WriteString(sep)
+ builder.WriteString(fmt.Sprintf("%s", pathSegment.Debug()))
+ sep = "."
+ }
+ builder.WriteString(": ")
+ sep = ""
+ for _, value := range item.Value {
+ builder.WriteString(sep)
+ builder.WriteString(fmt.Sprintf("%s", value.Debug()))
+ sep = ", "
+ }
+ return builder.String()
}
-func ConcatData(first []Atom, second []Atom) []Atom {
- res := make([]Atom, 0, len(first) + len(second))
+func ConcatData(first []AtomOLD, second []AtomOLD) []AtomOLD {
+ res := make([]AtomOLD, 0, len(first) + len(second))
res = append(res, first...)
res = append(res, second...)
return res
}
-func Atomise(in []Value) (out []Atom) {
+func Atomise(in []ValueOLD) (out []AtomOLD) {
numAtoms := 0
for _, value := range in {
switch v := value.(type) {
@@ -64,7 +297,7 @@ func Atomise(in []Value) (out []Atom) {
panic("Invalid WalkValue")
}
}
- out = make([]Atom, 0, numAtoms)
+ out = make([]AtomOLD, 0, numAtoms)
for _, value := range in {
out = value.Atomise(out)
}
@@ -96,11 +329,11 @@ func (err CompoundError) Error() string {
}
type CompoundResult struct {
- value Value
+ value ValueOLD
error error
}
-func Compound(in []Atom) (out []Value, error error) {
+func Compound(in []AtomOLD) (out []ValueOLD, error error) {
numValues := 0
i := 0
inString := false
@@ -118,7 +351,7 @@ func Compound(in []Atom) (out []Value, error error) {
}
}
i = 0
- out = make([]Value, 0, numValues)
+ out = make([]ValueOLD, 0, numValues)
for {
if i >= len(in) {
break