github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/lib/stringlib/pattern/pattern.go (about)

     1  package pattern
     2  
     3  import "errors"
     4  
     5  // A Pattern is a data structure able to interpret a Lua "pattern" (see e.g.
     6  // https://www.lua.org/manual/5.3/manual.html#6.4.1).
     7  type Pattern struct {
     8  	items                  []patternItem
     9  	captureCount           int
    10  	startAnchor, endAnchor bool
    11  }
    12  
    13  // New returns a new Pattern built from the given string (or an error if it is
    14  // not a valid pattern string).
    15  func New(ptn string) (*Pattern, error) {
    16  	pb := &patternBuilder{ptn: ptn}
    17  	return pb.getPattern()
    18  }
    19  
    20  // MatchFromStart returns a slice of Capture instances that match the given
    21  // string, starting from the `init` index.
    22  func (p *Pattern) MatchFromStart(s string, init int, budget uint64) (captures []Capture, used uint64) {
    23  	defer func() {
    24  		if r := recover(); r == budgetConsumed {
    25  			captures = nil
    26  			used = budget + 1
    27  		}
    28  	}()
    29  	matcher := patternMatcher{
    30  		Pattern: *p,
    31  		s:       s,
    32  		si:      init,
    33  		budget:  budget,
    34  	}
    35  	captures = matcher.findFromStart()
    36  	return captures, budget - matcher.budget
    37  }
    38  
    39  // Match returns a slice of Capture instances that match the given
    40  // string, starting from the `init` index.
    41  func (p *Pattern) Match(s string, init int, budget uint64) (captures []Capture, used uint64) {
    42  	defer func() {
    43  		if r := recover(); r == budgetConsumed {
    44  			captures = nil
    45  			used = budget + 1
    46  		}
    47  	}()
    48  	matcher := patternMatcher{
    49  		Pattern: *p,
    50  		s:       s,
    51  		si:      init,
    52  		budget:  budget,
    53  	}
    54  	captures = matcher.find()
    55  	return captures, budget - matcher.budget
    56  }
    57  
    58  // A Capture represents a matching substring.
    59  type Capture struct {
    60  	start, end int
    61  }
    62  
    63  // Start index of the capture.
    64  func (c Capture) Start() int {
    65  	return c.start
    66  }
    67  
    68  // End index of the capture.
    69  func (c Capture) End() int {
    70  	return c.end
    71  }
    72  
    73  // IsEmpty is trye if the Capture is empty.
    74  func (c Capture) IsEmpty() bool {
    75  	return c.end == -1
    76  }
    77  
    78  type patternItemType byte
    79  
    80  const (
    81  	ptnOnce patternItemType = iota
    82  	ptnGreedyRepeat
    83  	ptnGreedyRepeatOnce
    84  	ptnRepeat
    85  	ptnOptional
    86  	ptnCapture
    87  	ptnBalanced
    88  	ptnFrontier
    89  	ptnStartCapture
    90  	ptnEndCapture
    91  )
    92  
    93  type patternItem struct {
    94  	bytes   byteSet
    95  	ptnType patternItemType
    96  }
    97  
    98  var errInvalidPattern = errors.New("malformed pattern")
    99  var errUnfinishedCapture = errors.New("unfinished capture")
   100  var errInvalidPatternCapture = errors.New("invalid pattern capture")
   101  var errPatternTooComplex = errors.New("pattern too complex")