forked from mirror/glob
tests
This commit is contained in:
parent
d400ac872c
commit
f313fe3570
74
lexer.go
74
lexer.go
|
@ -27,13 +27,56 @@ const (
|
|||
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 {
|
||||
t itemType
|
||||
s 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 {
|
||||
|
@ -193,7 +236,7 @@ func lexInsideRange(l *lexer) stateFn {
|
|||
switch c {
|
||||
case inside_range_not:
|
||||
// only first char makes sense
|
||||
if l.pos == l.start {
|
||||
if l.pos-1 == l.start {
|
||||
l.emit(item_range_not)
|
||||
}
|
||||
|
||||
|
@ -221,6 +264,8 @@ func lexAny(l *lexer) stateFn {
|
|||
}
|
||||
|
||||
func lexRangeHiLo(l *lexer) stateFn {
|
||||
start := l.start
|
||||
|
||||
for {
|
||||
c := l.read()
|
||||
if c == eof {
|
||||
|
@ -228,22 +273,37 @@ func lexRangeHiLo(l *lexer) stateFn {
|
|||
return nil
|
||||
}
|
||||
|
||||
switch c {
|
||||
case inside_range_minus:
|
||||
if l.pos-l.start != 1 {
|
||||
l.errorf("unexpected length of char inside range")
|
||||
l.errorf("unexpected length of range: single character expected before minus")
|
||||
return nil
|
||||
}
|
||||
|
||||
switch c {
|
||||
case inside_range_minus:
|
||||
l.emit(item_range_minus)
|
||||
|
||||
case range_close:
|
||||
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
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
if hi < lo {
|
||||
return nil, nil, fmt.Errorf("hi character should be greater than lo")
|
||||
}
|
||||
|
||||
hi = r[0]
|
||||
|
||||
case item_range_chars:
|
||||
|
@ -120,6 +124,10 @@ func parserRange(lexer *lexer, separators string) ([]token, parseFn, error) {
|
|||
if isRange {
|
||||
return []token{token{match.Between{lo, hi, not}, ""}}, parserMain, nil
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
package glob
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseString(t *testing.T) {
|
||||
lexer := newLexer("hello")
|
||||
fmt.Println(lexer.nextItem())
|
||||
fmt.Println(lexer.nextItem())
|
||||
fmt.Println(lexer.nextItem())
|
||||
// lexer := newLexer("hello")
|
||||
// fmt.Println(lexer.nextItem())
|
||||
// fmt.Println(lexer.nextItem())
|
||||
// fmt.Println(lexer.nextItem())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue