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  }