elvish/glob/parse.go

93 lines
1.4 KiB
Go
Raw Normal View History

2016-02-08 02:33:57 +08:00
package glob
import (
"bytes"
"unicode/utf8"
)
2016-02-08 06:23:16 +08:00
// Parse parses a pattern.
2016-02-08 02:33:57 +08:00
func Parse(s string) Pattern {
segments := []Segment{}
add := func(seg Segment) {
segments = append(segments, seg)
}
p := &parser{s, 0, 0}
rune:
for {
r := p.next()
switch r {
2016-02-08 06:23:16 +08:00
case eof:
2016-02-08 02:33:57 +08:00
break rune
case '?':
add(Wild{Question, false, nil})
2016-02-08 02:33:57 +08:00
case '*':
n := 1
for p.next() == '*' {
n++
}
p.backup()
if n == 1 {
add(Wild{Star, false, nil})
2016-02-08 02:33:57 +08:00
} else {
add(Wild{StarStar, false, nil})
2016-02-08 02:33:57 +08:00
}
case '/':
for p.next() == '/' {
}
p.backup()
2017-02-03 03:15:42 +08:00
add(Slash{})
2016-02-08 02:33:57 +08:00
default:
var literal bytes.Buffer
literal:
for {
switch r {
2016-02-08 06:23:16 +08:00
case '?', '*', '/', eof:
2016-02-08 02:33:57 +08:00
break literal
case '\\':
r = p.next()
2016-02-08 06:23:16 +08:00
if r == eof {
2016-02-08 02:33:57 +08:00
break literal
}
literal.WriteRune(r)
default:
literal.WriteRune(r)
}
r = p.next()
}
p.backup()
2017-02-03 03:15:42 +08:00
add(Literal{literal.String()})
2016-02-08 02:33:57 +08:00
}
}
return Pattern{segments, ""}
2016-02-08 02:33:57 +08:00
}
// XXX Contains duplicate code with parse/parser.go.
type parser struct {
src string
pos int
overEOF int
}
2016-02-08 06:23:16 +08:00
const eof rune = -1
2016-02-08 02:33:57 +08:00
func (ps *parser) next() rune {
if ps.pos == len(ps.src) {
2016-02-08 06:23:16 +08:00
ps.overEOF++
return eof
2016-02-08 02:33:57 +08:00
}
r, s := utf8.DecodeRuneInString(ps.src[ps.pos:])
ps.pos += s
return r
}
func (ps *parser) backup() {
if ps.overEOF > 0 {
2016-02-08 06:23:16 +08:00
ps.overEOF--
2016-02-08 02:33:57 +08:00
return
}
_, s := utf8.DecodeLastRuneInString(ps.src[:ps.pos])
ps.pos -= s
}