walk.go (4969B)
1 package walk 2 3 import ( 4 "fmt" 5 "strings" 6 "unicode/utf8" 7 ) 8 9 type valueIter struct { 10 values []Value 11 index int 12 } 13 func (iter *valueIter) Next() Edible { 14 if iter.index >= len(iter.values) { 15 return nil 16 } 17 iter.index += 1 18 return iter.values[iter.index - 1] 19 } 20 21 func NewValueIter(values []Value) StructureIter { 22 return &valueIter { 23 values: values, 24 index: 0, 25 } 26 } 27 28 type OutputList interface { 29 outputList() 30 } 31 32 type StructureIter interface { 33 Next() Edible 34 } 35 36 type Edible interface { 37 edible() 38 } 39 40 type Atom interface { 41 Edible 42 atom() 43 } 44 45 type Scalar interface { 46 Atom 47 Value 48 } 49 50 type Structure interface { 51 Value 52 structure() 53 Iter() StructureIter 54 } 55 56 type Value interface { 57 Edible 58 value() 59 Debug() string 60 } 61 62 type Terminal interface { 63 Atom 64 terminal() 65 } 66 67 type ValueList []Value 68 func (_ ValueList) outputList() {} 69 70 type RuneList []StringRuneAtom 71 func (_ RuneList) outputList() {} 72 73 type NullScalar struct{} 74 func (_ NullScalar) edible() {} 75 func (_ NullScalar) atom() {} 76 func (_ NullScalar) value() {} 77 func (_ NullScalar) Debug() string { 78 return "null" 79 } 80 81 type BoolScalar bool 82 func (_ BoolScalar) edible() {} 83 func (_ BoolScalar) atom() {} 84 func (_ BoolScalar) value() {} 85 func (b BoolScalar) Debug() string { 86 if b { 87 return "true" 88 } 89 return "false" 90 } 91 92 type NumberScalar float64 93 func (_ NumberScalar) edible() {} 94 func (_ NumberScalar) atom() {} 95 func (_ NumberScalar) value() {} 96 func (n NumberScalar) Debug() string { 97 return fmt.Sprintf("%v", float64(n)) 98 } 99 100 type StringStructure string 101 func (_ StringStructure) edible() {} 102 func (_ StringStructure) value() {} 103 func (_ StringStructure) structure() {} 104 func (s StringStructure) Iter() StructureIter { 105 return &stringStructureIter { 106 string: string(s), 107 position: 0, 108 } 109 } 110 func (s StringStructure) Debug() string { 111 return fmt.Sprintf("%q", string(s)) 112 } 113 114 type stringStructureIter struct { 115 string string 116 position int 117 } 118 func (iter *stringStructureIter) Next() Edible { 119 if iter.position == -1 { 120 return nil 121 } 122 r, width := utf8.DecodeRuneInString(iter.string[iter.position:]) 123 if width == 0 { 124 iter.position = -1 125 return StringEndTerminal{} 126 } 127 iter.position += width 128 return StringRuneAtom(r) 129 } 130 131 type StringBeginTerminal struct{} 132 func (_ StringBeginTerminal) edible() {} 133 func (_ StringBeginTerminal) atom() {} 134 func (_ StringBeginTerminal) terminal() {} 135 136 type StringEndTerminal struct{} 137 func (_ StringEndTerminal) edible() {} 138 func (_ StringEndTerminal) atom() {} 139 func (_ StringEndTerminal) terminal() {} 140 141 type StringRuneAtom rune 142 func (_ StringRuneAtom) edible() {} 143 func (_ StringRuneAtom) atom() {} 144 145 type ArrayStructure []Value 146 func (_ ArrayStructure) edible() {} 147 func (_ ArrayStructure) value() {} 148 func (_ ArrayStructure) structure() {} 149 func (array ArrayStructure) Iter() StructureIter { 150 return &arrayStructureIter { 151 array: []Value(array), 152 index: 0, 153 } 154 } 155 func (array ArrayStructure) Debug() string { 156 builder := strings.Builder{} 157 builder.WriteRune('[') 158 var sep string 159 for _, element := range array { 160 builder.WriteString(sep) 161 builder.WriteString(fmt.Sprintf("%v", element)) 162 sep = ", " 163 } 164 builder.WriteRune(']') 165 return builder.String() 166 } 167 168 type arrayStructureIter struct { 169 array []Value 170 index int 171 } 172 func (iter *arrayStructureIter) Next() Edible { 173 if iter.index > len(iter.array) { 174 return nil 175 } 176 if iter.index == len(iter.array) { 177 iter.index += 1 178 return ArrayEndTerminal{} 179 } 180 iter.index += 1 181 return iter.array[iter.index - 1] 182 } 183 184 type ArrayBeginTerminal struct{} 185 func (_ ArrayBeginTerminal) edible() {} 186 func (_ ArrayBeginTerminal) atom() {} 187 func (_ ArrayBeginTerminal) terminal() {} 188 189 type ArrayEndTerminal struct{} 190 func (_ ArrayEndTerminal) edible() {} 191 func (_ ArrayEndTerminal) atom() {} 192 func (_ ArrayEndTerminal) terminal() {} 193 194 type MapStructure map[string]Value 195 func (_ MapStructure) edible() {} 196 func (_ MapStructure) value() {} 197 func (_ MapStructure) structure() {} 198 func (m MapStructure) Debug() string { 199 builder := strings.Builder{} 200 builder.WriteRune('{') 201 var sep string 202 for key, value := range m { 203 builder.WriteString(sep) 204 builder.WriteString(fmt.Sprintf("%q", key)) 205 builder.WriteString(": ") 206 builder.WriteString(fmt.Sprintf("%q", value)) 207 sep = ", " 208 } 209 builder.WriteRune('}') 210 return builder.String() 211 } 212 213 type MapBeginTerminal struct{} 214 func (_ MapBeginTerminal) edible() {} 215 func (_ MapBeginTerminal) atom() {} 216 func (_ MapBeginTerminal) terminal() {} 217 218 type MapEndTerminal struct{} 219 func (_ MapEndTerminal) edible() {} 220 func (_ MapEndTerminal) atom() {} 221 func (_ MapEndTerminal) terminal() {} 222 223 type WalkItem struct { 224 Value ValueList 225 Path ValueList 226 } 227 228 func (item WalkItem) Debug() string { 229 builder := strings.Builder{} 230 var sep string 231 for _, pathSegment := range item.Path { 232 builder.WriteString(sep) 233 builder.WriteString(fmt.Sprintf("%s", pathSegment.Debug())) 234 sep = "." 235 } 236 builder.WriteString(": ") 237 sep = "" 238 for _, value := range item.Value { 239 builder.WriteString(sep) 240 builder.WriteString(fmt.Sprintf("%s", value.Debug())) 241 sep = ", " 242 } 243 return builder.String() 244 }