22// of this source code is governed by a BSD-style license that can be found in
33// the LICENSE file.
44
5- package manifest
5+ // Package strparse provides facilities for parsing strings, intended for use in
6+ // tests and debug input.
7+ package strparse
68
79import (
810 "fmt"
@@ -14,31 +16,32 @@ import (
1416 "github.com/cockroachdb/pebble/internal/base"
1517)
1618
17- // debugParser is a helper used to implement parsing of debug strings, like
18- // ParseFileMetadataDebug.
19+ // Parser is a helper used to implement parsing of strings, like
20+ // manifest. ParseFileMetadataDebug.
1921//
2022// It takes a string and splits it into tokens. Tokens are separated by
21- // whitespace; in addition separators "_-[]()" are always separate tokens. For
22- // example, the string `000001:[a - b]` results in tokens `000001`,
23- // `:`, `[`, `a`, `-`, `b`, `]`, .
23+ // whitespace; in addition user-specified separators are also always separate
24+ // tokens. For example, when passed the separators `:-[]();` the string
25+ // `000001:[a - b]` results in tokens `000001`, ` :`, `[`, `a`, `-`, `b`, `]`, .
2426//
25- // All debugParser methods throw panics instead of returning errors. The code
26- // that uses a debugParser can recover them and convert them to errors.
27- type debugParser struct {
27+ // All Parser methods throw panics instead of returning errors. The code
28+ // that uses a Parser can recover them and convert them to errors.
29+ type Parser struct {
2830 original string
2931 tokens []string
3032 lastToken string
3133}
3234
33- const debugParserSeparators = ":-[]();"
34-
35- func makeDebugParser (s string ) debugParser {
36- p := debugParser {
37- original : s ,
35+ // MakeParser constructs a new Parser that converts any instance of the runes
36+ // contained in [separators] into separate tokens, and consumes the provided
37+ // input string.
38+ func MakeParser (separators string , input string ) Parser {
39+ p := Parser {
40+ original : input ,
3841 }
39- for _ , f := range strings .Fields (s ) {
42+ for _ , f := range strings .Fields (input ) {
4043 for f != "" {
41- pos := strings .IndexAny (f , debugParserSeparators )
44+ pos := strings .IndexAny (f , separators )
4245 if pos == - 1 {
4346 p .tokens = append (p .tokens , f )
4447 break
@@ -54,13 +57,13 @@ func makeDebugParser(s string) debugParser {
5457}
5558
5659// Done returns true if there are no more tokens.
57- func (p * debugParser ) Done () bool {
60+ func (p * Parser ) Done () bool {
5861 return len (p .tokens ) == 0
5962}
6063
6164// Peek returns the next token, without consuming the token. Returns "" if there
6265// are no more tokens.
63- func (p * debugParser ) Peek () string {
66+ func (p * Parser ) Peek () string {
6467 if p .Done () {
6568 p .lastToken = ""
6669 return ""
@@ -70,7 +73,7 @@ func (p *debugParser) Peek() string {
7073}
7174
7275// Next returns the next token, or "" if there are no more tokens.
73- func (p * debugParser ) Next () string {
76+ func (p * Parser ) Next () string {
7477 res := p .Peek ()
7578 if res != "" {
7679 p .tokens = p .tokens [1 :]
@@ -79,15 +82,15 @@ func (p *debugParser) Next() string {
7982}
8083
8184// Remaining returns all the remaining tokens, separated by spaces.
82- func (p * debugParser ) Remaining () string {
85+ func (p * Parser ) Remaining () string {
8386 res := strings .Join (p .tokens , " " )
8487 p .tokens = nil
8588 return res
8689}
8790
8891// Expect consumes the next tokens, verifying that they exactly match the
8992// arguments.
90- func (p * debugParser ) Expect (tokens ... string ) {
93+ func (p * Parser ) Expect (tokens ... string ) {
9194 for _ , tok := range tokens {
9295 if res := p .Next (); res != tok {
9396 p .Errf ("expected %q, got %q" , tok , res )
@@ -97,7 +100,7 @@ func (p *debugParser) Expect(tokens ...string) {
97100
98101// TryLevel tries to parse a token as a level (e.g. L1, L0.2). If successful,
99102// the token is consumed.
100- func (p * debugParser ) TryLevel () (level int , ok bool ) {
103+ func (p * Parser ) TryLevel () (level int , ok bool ) {
101104 t := p .Peek ()
102105 if regexp .MustCompile (`^L[0-9](|\.[0-9]+)$` ).MatchString (t ) {
103106 p .Next ()
@@ -107,7 +110,7 @@ func (p *debugParser) TryLevel() (level int, ok bool) {
107110}
108111
109112// Level parses the next token as a level.
110- func (p * debugParser ) Level () int {
113+ func (p * Parser ) Level () int {
111114 level , ok := p .TryLevel ()
112115 if ! ok {
113116 p .Errf ("cannot parse level" )
@@ -116,7 +119,7 @@ func (p *debugParser) Level() int {
116119}
117120
118121// Int parses the next token as an integer.
119- func (p * debugParser ) Int () int {
122+ func (p * Parser ) Int () int {
120123 x , err := strconv .Atoi (p .Next ())
121124 if err != nil {
122125 p .Errf ("cannot parse number: %v" , err )
@@ -125,7 +128,7 @@ func (p *debugParser) Int() int {
125128}
126129
127130// Uint64 parses the next token as an uint64.
128- func (p * debugParser ) Uint64 () uint64 {
131+ func (p * Parser ) Uint64 () uint64 {
129132 x , err := strconv .ParseUint (p .Next (), 10 , 64 )
130133 if err != nil {
131134 p .Errf ("cannot parse number: %v" , err )
@@ -134,36 +137,28 @@ func (p *debugParser) Uint64() uint64 {
134137}
135138
136139// Uint64 parses the next token as a sequence number.
137- func (p * debugParser ) SeqNum () base.SeqNum {
140+ func (p * Parser ) SeqNum () base.SeqNum {
138141 return base .ParseSeqNum (p .Next ())
139142}
140143
141144// FileNum parses the next token as a FileNum.
142- func (p * debugParser ) FileNum () base.FileNum {
145+ func (p * Parser ) FileNum () base.FileNum {
143146 return base .FileNum (p .Int ())
144147}
145148
146149// DiskFileNum parses the next token as a DiskFileNum.
147- func (p * debugParser ) DiskFileNum () base.DiskFileNum {
150+ func (p * Parser ) DiskFileNum () base.DiskFileNum {
148151 return base .DiskFileNum (p .Int ())
149152}
150153
151154// InternalKey parses the next token as an internal key.
152- func (p * debugParser ) InternalKey () base.InternalKey {
155+ func (p * Parser ) InternalKey () base.InternalKey {
153156 return base .ParseInternalKey (p .Next ())
154157}
155158
156159// Errf panics with an error which includes the original string and the last
157160// token.
158- func (p * debugParser ) Errf (format string , args ... any ) {
161+ func (p * Parser ) Errf (format string , args ... any ) {
159162 msg := fmt .Sprintf (format , args ... )
160163 panic (errors .Errorf ("error parsing %q at token %q: %s" , p .original , p .lastToken , msg ))
161164}
162-
163- // errFromPanic can be used in a recover block to convert panics into errors.
164- func errFromPanic (r any ) error {
165- if err , ok := r .(error ); ok {
166- return err
167- }
168- return errors .Errorf ("%v" , r )
169- }
0 commit comments