This commit is contained in:
s.kamardin 2015-12-25 21:08:54 +03:00
parent d400ac872c
commit f313fe3570
4 changed files with 181 additions and 14 deletions

View File

@ -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
}
if l.pos-l.start != 1 {
l.errorf("unexpected length of char inside range")
return nil
}
switch c {
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)
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)
}
}
}

100
lexer_test.go Normal file
View File

@ -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
}
}
}
}

View File

@ -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
}
}

View File

@ -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())
}