package asld import "fmt" // Walker.... texas ranger. // Except he's a cringe conservative. // // This is also cringe but not for cringe reasons. func (w walker) Debug_PRINT() { for index, b := range w.content { out := string(b) if w.position == index { out = "<[>" + out + "<]>" } print(out) } print("\n") } func (w walker) SliceInner() (walker, bool) { // the !ok scenario here is only if the code is bad s, ok := byByte[w.Current()] // Debug if !ok { panic(w) } var height uint for pos := w.position + 1; pos < w.len; pos++ { curr := w.content[pos] if curr == s.self && s.self != s.closer { height++ continue } if curr == s.closer { if height == 0 { return newWalker(w.content[w.position+1 : pos]), ok } height-- } } return w, false } // Sub returns a subwalker from the current position func (w walker) Sub() walker { w.content = w.content[w.position:] w.len = len(w.content) w.position = 0 return w } type walker struct { content []byte len int position int } func newWalker(data []byte) walker { return walker{ content: data, len: len(data), } } // Until returns a subwalker from position 0 to the current position func (w walker) Until() walker { w.content = w.content[:w.position] w.len = len(w.content) return w } // ToOrStay will stay at where the walker is if b is the // same as the current walker position. // // Otherwise, calls To func (w walker) ToOrStay(b byte) (walker, bool) { if w.Current() == b { return w, true } return w.To(b) } func (w walker) To(b byte) (walker, bool) { for pos := w.position + 1; pos < w.len; pos++ { if w.content[pos] == b { w.position = pos return w, true } } return w, false } func (w walker) Next() (walker, bool) { w, ok := w.ToNext() return w.Sub(), ok } func (w walker) ToNext() (walker, bool) { for pos := w.position + 1; pos < w.len; pos++ { if in(symbolsRaw, w.content[pos]) { w.position = pos return w, true } } return w, false } // CommaOrEnd walks to the next comma, or, if none // is present in the current walker scope, returns // itself with status statusWalkerNotAffected. func (w walker) CommaOrEnd() (walkerStatus, error) { if w.Current() == ',' { w.position++ } for pos := w.position; pos < w.len; pos++ { if in(openRaw, w.content[pos]) { sb, ok := byByte[w.content[pos]] if !ok { panic("ok someone fucked up somewhere") } w, ok = w.To(sb.closer) if !ok { return walkerStatus{ status: statusError, walker: w, }, fmt.Errorf("%w %s", ErrNoMatching, string(sb.closer)) } pos = w.position continue } if w.content[pos] == ',' { w.position = pos return walkerStatus{ status: statusOK, walker: w, }, nil } } return walkerStatus{ status: statusWalkerNotAffected, walker: w, }, nil } func (w walker) Current() byte { return w.content[w.position] } func (w walker) CurrentSymbol() (Symbol, bool) { b, ok := byByte[w.Current()] return b, ok } func (w walker) String() string { if w.Current() == '"' { w, _ = w.SliceInner() } return string(w.content) }