github.com/jmigpin/editor@v1.6.0/util/parseutil/scparse.go (about) 1 package parseutil 2 3 import ( 4 "fmt" 5 ) 6 7 // scanner parse utility funcs 8 type ScParse struct { 9 sc *Scanner 10 M *ScMatch 11 cache struct { 12 cfs map[string]*ScParseCacheFn 13 } 14 } 15 16 func (p *ScParse) init(sc *Scanner) { 17 p.sc = sc 18 p.M = &sc.M 19 p.cache.cfs = map[string]*ScParseCacheFn{} 20 } 21 22 //---------- 23 24 func (p *ScParse) And(fns ...ScFn) ScFn { 25 return func() error { 26 return p.M.And(fns...) 27 } 28 } 29 func (p *ScParse) Or(fns ...ScFn) ScFn { 30 return func() error { 31 return p.M.Or(fns...) 32 } 33 } 34 func (p *ScParse) Optional(fn ScFn) ScFn { 35 return func() error { 36 return p.M.Optional(fn) 37 } 38 } 39 40 //---------- 41 42 func (p *ScParse) Loop2(fn ScFn) ScFn { 43 return p.Loop(fn, nil, false) 44 } 45 func (p *ScParse) Loop(fn, sep ScFn, lastSep bool) ScFn { 46 return func() error { 47 sepPos := p.sc.KeepPos() 48 for first := true; ; first = false { 49 // seperator 50 if sep != nil && p.sc.Reverse { 51 if err := p.sc.RestorePosOnErr(sep); err != nil { 52 if first && !lastSep { 53 return fmt.Errorf("unexpected last separator") 54 } 55 } 56 } 57 // fn 58 if err := p.sc.RestorePosOnErr(fn); err != nil { 59 if IsScFatalError(err) { 60 return err 61 } 62 if first { 63 return err 64 } 65 // seperator 66 if sep != nil && !p.sc.Reverse { 67 if !first && !lastSep { 68 sepPos.Restore() 69 return fmt.Errorf("unexpected last separator") 70 } 71 } 72 return nil 73 } 74 // separator 75 if sep != nil && !p.sc.Reverse { 76 sepPos = p.sc.KeepPos() 77 if err := p.sc.RestorePosOnErr(sep); err != nil { 78 return nil // no sep, last entry 79 } 80 } 81 } 82 } 83 } 84 func (p *ScParse) Rune(ru rune) ScFn { 85 return func() error { 86 return p.M.Rune(ru) 87 } 88 } 89 func (p *ScParse) RuneAny(rs []rune) ScFn { 90 return func() error { 91 return p.M.RuneAny(rs) 92 } 93 } 94 func (p *ScParse) RuneFn(fn func(rune) bool) ScFn { 95 return func() error { 96 return p.M.RuneFn(fn) 97 } 98 } 99 func (p *ScParse) Sequence(seq string) ScFn { 100 return func() error { 101 return p.M.Sequence(seq) 102 } 103 } 104 func (p *ScParse) SequenceMid(seq string) ScFn { 105 return func() error { 106 return p.M.SequenceMid(seq) 107 } 108 } 109 110 //---------- 111 112 func (p *ScParse) RegexpFromStartCached(res string, maxLen int) ScFn { 113 return func() error { 114 return p.M.RegexpFromStartCached(res, maxLen) 115 } 116 } 117 func (p *ScParse) DoubleQuotedString(maxLen int) ScFn { 118 return func() error { 119 return p.M.DoubleQuotedString(maxLen) 120 } 121 } 122 func (p *ScParse) QuotedString2(esc rune, maxLen1, maxLen2 int) ScFn { 123 return func() error { 124 return p.M.QuotedString2(esc, maxLen1, maxLen2) 125 } 126 } 127 func (p *ScParse) EscapeAny(esc rune) ScFn { 128 return func() error { 129 return p.M.EscapeAny(esc) 130 } 131 } 132 func (p *ScParse) NRunes(n int) ScFn { 133 return func() error { 134 return p.M.NRunes(n) 135 } 136 } 137 func (p *ScParse) Spaces(includeNL bool, escape rune) ScFn { 138 return func() error { 139 return p.M.Spaces(includeNL, escape) 140 } 141 } 142 func (p *ScParse) OptionalSpaces() ScFn { 143 return p.Optional(p.Spaces(true, 0)) 144 } 145 func (p *ScParse) Integer() ScFn { 146 return p.M.Integer 147 } 148 func (p *ScParse) Float() ScFn { 149 return p.M.Float 150 } 151 152 //---------- 153 154 // WARNING: best used when there are no closure variables in the function, otherwise the variables will contain values of previous runs 155 func (p *ScParse) GetCacheFunc(name string) *ScParseCacheFn { 156 cf, ok := p.cache.cfs[name] 157 if ok { 158 return cf 159 } 160 cf = &ScParseCacheFn{p: p, name: name} 161 p.cache.cfs[name] = cf 162 return cf 163 } 164 165 //---------- 166 167 func (p *ScParse) FatalOnErr(str string, fn ScFn) ScFn { 168 return func() error { 169 err := fn() 170 if err != nil { 171 if !IsScFatalError(err) { 172 fe := &ScFatalError{} 173 fe.Err = fmt.Errorf("%v: %w", str, err) 174 fe.Pos = p.sc.Pos 175 err = fe 176 } 177 } 178 return err 179 } 180 } 181 182 //---------- 183 //---------- 184 //---------- 185 186 // scanner parse cache func 187 type ScParseCacheFn struct { 188 p *ScParse 189 name string 190 fn ScFn 191 192 PreRun func() 193 Data func() any 194 } 195 196 func (cf *ScParseCacheFn) IsSet() bool { 197 return cf.fn != nil 198 } 199 func (cf *ScParseCacheFn) Set(fn ScFn) { 200 cf.fn = fn 201 } 202 func (cf *ScParseCacheFn) Run() error { 203 if cf.PreRun != nil { 204 cf.PreRun() 205 } 206 return cf.fn() 207 }