github.com/jmigpin/editor@v1.6.0/util/parseutil/scanner.go (about) 1 package parseutil 2 3 import ( 4 "fmt" 5 "io" 6 "strconv" 7 "unicode/utf8" 8 ) 9 10 // not safe to parse concurrently (match/parse uses closures) 11 type Scanner struct { 12 Src []byte 13 Pos int 14 M ScMatch 15 P ScParse 16 17 Reverse bool // read direction 18 Debug bool 19 ErrFilename string // used for errors only 20 } 21 22 func NewScanner() *Scanner { 23 sc := &Scanner{} 24 sc.M.init(sc) 25 sc.P.init(sc) 26 return sc 27 } 28 29 //---------- 30 31 func (sc *Scanner) SetSrc(src []byte) { 32 sc.Src = src 33 sc.Pos = 0 34 } 35 36 //---------- 37 38 func (sc *Scanner) ReadRune() (rune, error) { 39 ru := rune(0) 40 size := 0 41 if sc.Reverse { 42 ru, size = utf8.DecodeLastRune(sc.Src[:sc.Pos]) 43 size = -size // decrease pos 44 } else { 45 ru, size = utf8.DecodeRune(sc.Src[sc.Pos:]) 46 } 47 if size == 0 { 48 return 0, io.EOF 49 } 50 if sc.Debug { 51 fmt.Printf("%v: %q\n", sc.Pos, ru) 52 } 53 sc.Pos += size 54 55 return ru, nil 56 } 57 func (sc *Scanner) PeekRune() (rune, error) { 58 pos0 := sc.KeepPos() 59 ru, err := sc.ReadRune() 60 pos0.Restore() 61 return ru, err 62 } 63 64 //---------- 65 66 func (sc *Scanner) KeepPos() ScannerPos { 67 return ScannerPos{sc: sc, Pos: sc.Pos} 68 } 69 70 func (sc *Scanner) RestorePosOnErr(fn func() error) error { 71 pos0 := sc.KeepPos() 72 if err := fn(); err != nil { 73 pos0.Restore() 74 return err 75 } 76 return nil 77 } 78 79 //---------- 80 81 func (sc *Scanner) NewValueKeeper() *ScValueKeeper { 82 return &ScValueKeeper{sc: sc} 83 } 84 85 //---------- 86 87 func (sc *Scanner) SrcErrorf(f string, args ...any) error { 88 return sc.SrcError(fmt.Errorf(f, args...)) 89 } 90 func (sc *Scanner) SrcError(err error) error { 91 return sc.SrcError2(err, 20) 92 } 93 func (sc *Scanner) SrcError2(err error, maxLen int) error { 94 filename := sc.ErrFilename 95 if filename == "" { 96 filename = "<bytes>" 97 } 98 99 // position 100 pos := sc.Pos 101 if pe, ok := err.(*ScPosError); ok { 102 pos = pe.Pos 103 } 104 if fe, ok := err.(*ScFatalError); ok { 105 pos = fe.Pos 106 } 107 108 line, col := IndexLineColumn2(sc.Src, pos) 109 str := SurroundingString(sc.Src, pos, maxLen) 110 return fmt.Errorf("%v:%d:%d: %v: %q", filename, line, col, err, str) 111 } 112 113 //---------- 114 //---------- 115 //---------- 116 117 type ScannerPos struct { 118 sc *Scanner 119 Pos int 120 } 121 122 func (sp *ScannerPos) Restore() { 123 sp.sc.Pos = sp.Pos 124 } 125 func (sp *ScannerPos) IsEmpty() bool { 126 return sp.Pos == sp.sc.Pos 127 } 128 func (sp *ScannerPos) Len() int { 129 start, end := sp.StartEnd() 130 return end - start 131 } 132 func (sp *ScannerPos) StartEnd() (int, int) { 133 start, end := sp.Pos, sp.sc.Pos 134 if start > end { // support reverse mode 135 start, end = end, start 136 } 137 return start, end 138 } 139 func (sp *ScannerPos) Bytes() []byte { 140 start, end := sp.StartEnd() 141 return sp.sc.Src[start:end] 142 } 143 144 //---------- 145 //---------- 146 //---------- 147 148 // error with position 149 type ScPosError struct { 150 Err error 151 Pos int 152 } 153 154 func (e *ScPosError) Error() string { 155 return e.Err.Error() 156 } 157 158 //---------- 159 160 type ScFatalError struct { 161 ScPosError 162 } 163 164 func IsScFatalError(err error) bool { 165 _, ok := err.(*ScFatalError) 166 return ok 167 } 168 169 //---------- 170 //---------- 171 //---------- 172 173 type ScValueKeeper struct { 174 sc *Scanner 175 Value any 176 } 177 178 func (vk *ScValueKeeper) Reset() { 179 vk.Value = nil 180 } 181 182 //---------- 183 184 func (vk *ScValueKeeper) KeepBytes(fn ScFn) ScFn { 185 return func() error { 186 pos0 := vk.sc.KeepPos() 187 err := fn() 188 vk.Value = pos0.Bytes() 189 return err 190 } 191 } 192 func (vk *ScValueKeeper) KeepValue(fn ScValueFn) ScFn { 193 return func() error { 194 v, err := fn() 195 vk.Value = v 196 return err 197 } 198 } 199 200 //---------- 201 202 func (vk *ScValueKeeper) BytesOrNil() []byte { 203 if b, ok := vk.Value.([]byte); ok { 204 return b 205 } 206 return nil 207 } 208 209 //---------- 210 211 func (vk *ScValueKeeper) Int() (int, error) { 212 b, ok := vk.Value.([]byte) 213 if !ok { 214 return 0, fmt.Errorf("not []byte") 215 } 216 v, err := strconv.ParseInt(string(b), 10, 64) 217 if err != nil { 218 return 0, err 219 } 220 return int(v), nil 221 } 222 func (vk *ScValueKeeper) IntOrZero() int { 223 if v, err := vk.Int(); err == nil { 224 return v 225 } 226 return 0 227 } 228 229 //---------- 230 231 func (vk *ScValueKeeper) StringOptional() string { 232 if vk.Value == nil { 233 return "" 234 } 235 return vk.Value.(string) 236 } 237 func (vk *ScValueKeeper) String() string { 238 return vk.Value.(string) 239 } 240 241 //---------- 242 //---------- 243 //---------- 244 245 type ScFn func() error 246 type ScValueFn func() (any, error)