mirror of https://github.com/gobwas/glob.git
tests
This commit is contained in:
parent
d400ac872c
commit
f313fe3570
78
lexer.go
78
lexer.go
|
@ -27,13 +27,56 @@ const (
|
||||||
item_range_close
|
item_range_close
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (i itemType) String() string {
|
||||||
|
switch i {
|
||||||
|
case item_eof:
|
||||||
|
return "eof"
|
||||||
|
|
||||||
|
case item_error:
|
||||||
|
return "error"
|
||||||
|
|
||||||
|
case item_text:
|
||||||
|
return "text"
|
||||||
|
|
||||||
|
case item_any:
|
||||||
|
return "any"
|
||||||
|
|
||||||
|
case item_single:
|
||||||
|
return "single"
|
||||||
|
|
||||||
|
case item_range_open:
|
||||||
|
return "range_open"
|
||||||
|
|
||||||
|
case item_range_not:
|
||||||
|
return "range_not"
|
||||||
|
|
||||||
|
case item_range_lo:
|
||||||
|
return "range_lo"
|
||||||
|
|
||||||
|
case item_range_minus:
|
||||||
|
return "range_minus"
|
||||||
|
|
||||||
|
case item_range_hi:
|
||||||
|
return "range_hi"
|
||||||
|
|
||||||
|
case item_range_chars:
|
||||||
|
return "range_chars"
|
||||||
|
|
||||||
|
case item_range_close:
|
||||||
|
return "range_close"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "undef"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type item struct {
|
type item struct {
|
||||||
t itemType
|
t itemType
|
||||||
s string
|
s string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i item) String() string {
|
func (i item) String() string {
|
||||||
return fmt.Sprintf("%v[%s]", i.t, i.s)
|
return fmt.Sprintf("%v<%s>", i.t, i.s)
|
||||||
}
|
}
|
||||||
|
|
||||||
type lexer struct {
|
type lexer struct {
|
||||||
|
@ -193,7 +236,7 @@ func lexInsideRange(l *lexer) stateFn {
|
||||||
switch c {
|
switch c {
|
||||||
case inside_range_not:
|
case inside_range_not:
|
||||||
// only first char makes sense
|
// only first char makes sense
|
||||||
if l.pos == l.start {
|
if l.pos-1 == l.start {
|
||||||
l.emit(item_range_not)
|
l.emit(item_range_not)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +264,8 @@ func lexAny(l *lexer) stateFn {
|
||||||
}
|
}
|
||||||
|
|
||||||
func lexRangeHiLo(l *lexer) stateFn {
|
func lexRangeHiLo(l *lexer) stateFn {
|
||||||
|
start := l.start
|
||||||
|
|
||||||
for {
|
for {
|
||||||
c := l.read()
|
c := l.read()
|
||||||
if c == eof {
|
if c == eof {
|
||||||
|
@ -228,22 +273,37 @@ func lexRangeHiLo(l *lexer) stateFn {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if l.pos-l.start != 1 {
|
|
||||||
l.errorf("unexpected length of char inside range")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
switch c {
|
switch c {
|
||||||
case inside_range_minus:
|
case inside_range_minus:
|
||||||
|
if l.pos-l.start != 1 {
|
||||||
|
l.errorf("unexpected length of range: single character expected before minus")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
l.emit(item_range_minus)
|
l.emit(item_range_minus)
|
||||||
|
|
||||||
case range_close:
|
case range_close:
|
||||||
l.unread()
|
l.unread()
|
||||||
l.flush(item_range_hi)
|
|
||||||
|
if l.pos-l.start != 1 {
|
||||||
|
l.errorf("unexpected length of range: single character expected before close")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.emit(item_range_hi)
|
||||||
return lexRangeClose
|
return lexRangeClose
|
||||||
|
|
||||||
default:
|
default:
|
||||||
l.flush(item_range_lo)
|
if start != l.start {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if l.pos-l.start != 1 {
|
||||||
|
l.errorf("unexpected length of range: single character expected at the begining")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
l.emit(item_range_lo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
package glob
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLexGood(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
pattern string
|
||||||
|
items []item
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
pattern: "hello",
|
||||||
|
items: []item{
|
||||||
|
item{item_text, "hello"},
|
||||||
|
item{item_eof, ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "hello?",
|
||||||
|
items: []item{
|
||||||
|
item{item_text, "hello"},
|
||||||
|
item{item_single, "?"},
|
||||||
|
item{item_eof, ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "hello*",
|
||||||
|
items: []item{
|
||||||
|
item{item_text, "hello"},
|
||||||
|
item{item_any, "*"},
|
||||||
|
item{item_eof, ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "hello**",
|
||||||
|
items: []item{
|
||||||
|
item{item_text, "hello"},
|
||||||
|
item{item_any, "*"},
|
||||||
|
item{item_any, "*"},
|
||||||
|
item{item_eof, ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "[a-b]",
|
||||||
|
items: []item{
|
||||||
|
item{item_range_open, "["},
|
||||||
|
item{item_range_lo, "a"},
|
||||||
|
item{item_range_minus, "-"},
|
||||||
|
item{item_range_hi, "b"},
|
||||||
|
item{item_range_close, "]"},
|
||||||
|
item{item_eof, ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "[!a-b]",
|
||||||
|
items: []item{
|
||||||
|
item{item_range_open, "["},
|
||||||
|
item{item_range_not, "!"},
|
||||||
|
item{item_range_lo, "a"},
|
||||||
|
item{item_range_minus, "-"},
|
||||||
|
item{item_range_hi, "b"},
|
||||||
|
item{item_range_close, "]"},
|
||||||
|
item{item_eof, ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "[abc]",
|
||||||
|
items: []item{
|
||||||
|
item{item_range_open, "["},
|
||||||
|
item{item_range_chars, "abc"},
|
||||||
|
item{item_range_close, "]"},
|
||||||
|
item{item_eof, ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: "[!abc]",
|
||||||
|
items: []item{
|
||||||
|
item{item_range_open, "["},
|
||||||
|
item{item_range_not, "!"},
|
||||||
|
item{item_range_chars, "abc"},
|
||||||
|
item{item_range_close, "]"},
|
||||||
|
item{item_eof, ""},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
lexer := newLexer(test.pattern)
|
||||||
|
for _, exp := range test.items {
|
||||||
|
act := lexer.nextItem()
|
||||||
|
if act.t != exp.t {
|
||||||
|
t.Errorf("wrong item type: exp: %v; act: %v (%s vs %s)", exp.t, act.t, exp, act)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if act.s != exp.s {
|
||||||
|
t.Errorf("wrong item contents: exp: %q; act: %q (%s vs %s)", exp.s, act.s, exp, act)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -104,6 +104,10 @@ func parserRange(lexer *lexer, separators string) ([]token, parseFn, error) {
|
||||||
return nil, nil, fmt.Errorf("unexpected length of hi character")
|
return nil, nil, fmt.Errorf("unexpected length of hi character")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hi < lo {
|
||||||
|
return nil, nil, fmt.Errorf("hi character should be greater than lo")
|
||||||
|
}
|
||||||
|
|
||||||
hi = r[0]
|
hi = r[0]
|
||||||
|
|
||||||
case item_range_chars:
|
case item_range_chars:
|
||||||
|
@ -120,6 +124,10 @@ func parserRange(lexer *lexer, separators string) ([]token, parseFn, error) {
|
||||||
if isRange {
|
if isRange {
|
||||||
return []token{token{match.Between{lo, hi, not}, ""}}, parserMain, nil
|
return []token{token{match.Between{lo, hi, not}, ""}}, parserMain, nil
|
||||||
} else {
|
} else {
|
||||||
|
if len(chars) == 0 {
|
||||||
|
return nil, nil, fmt.Errorf("chars range should not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
return []token{token{match.RangeList{chars, not}, ""}}, parserMain, nil
|
return []token{token{match.RangeList{chars, not}, ""}}, parserMain, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package glob
|
package glob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseString(t *testing.T) {
|
func TestParseString(t *testing.T) {
|
||||||
lexer := newLexer("hello")
|
// lexer := newLexer("hello")
|
||||||
fmt.Println(lexer.nextItem())
|
// fmt.Println(lexer.nextItem())
|
||||||
fmt.Println(lexer.nextItem())
|
// fmt.Println(lexer.nextItem())
|
||||||
fmt.Println(lexer.nextItem())
|
// fmt.Println(lexer.nextItem())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue