github.com/oweisse/u-root@v0.0.0-20181109060735-d005ad25fef1/cmds/elvish/glob/parse.go (about) 1 package glob 2 3 import ( 4 "bytes" 5 "unicode/utf8" 6 ) 7 8 // Parse parses a pattern. 9 func Parse(s string) Pattern { 10 segments := []Segment{} 11 add := func(seg Segment) { 12 segments = append(segments, seg) 13 } 14 p := &parser{s, 0, 0} 15 16 rune: 17 for { 18 r := p.next() 19 switch r { 20 case eof: 21 break rune 22 case '?': 23 add(Wild{Question, false, nil}) 24 case '*': 25 n := 1 26 for p.next() == '*' { 27 n++ 28 } 29 p.backup() 30 if n == 1 { 31 add(Wild{Star, false, nil}) 32 } else { 33 add(Wild{StarStar, false, nil}) 34 } 35 case '/': 36 for p.next() == '/' { 37 } 38 p.backup() 39 add(Slash{}) 40 default: 41 var literal bytes.Buffer 42 literal: 43 for { 44 switch r { 45 case '?', '*', '/', eof: 46 break literal 47 case '\\': 48 r = p.next() 49 if r == eof { 50 break literal 51 } 52 literal.WriteRune(r) 53 default: 54 literal.WriteRune(r) 55 } 56 r = p.next() 57 } 58 p.backup() 59 add(Literal{literal.String()}) 60 } 61 } 62 return Pattern{segments, ""} 63 } 64 65 // XXX Contains duplicate code with parse/parser.go. 66 67 type parser struct { 68 src string 69 pos int 70 overEOF int 71 } 72 73 const eof rune = -1 74 75 func (ps *parser) next() rune { 76 if ps.pos == len(ps.src) { 77 ps.overEOF++ 78 return eof 79 } 80 r, s := utf8.DecodeRuneInString(ps.src[ps.pos:]) 81 ps.pos += s 82 return r 83 } 84 85 func (ps *parser) backup() { 86 if ps.overEOF > 0 { 87 ps.overEOF-- 88 return 89 } 90 _, s := utf8.DecodeLastRuneInString(ps.src[:ps.pos]) 91 ps.pos -= s 92 }