Index: src/0dev.org/parse/parse.go ================================================================== --- src/0dev.org/parse/parse.go +++ src/0dev.org/parse/parse.go @@ -88,9 +88,25 @@ if !n.Matched { return n, s } if n.Content == value { return n, r + } + return N{Matched: false, Content: "", Nodes: []N{n}}, s + } +} + +// Returns a parser that matches any single digit +// It could have been written as Any(String("0"),String("1"),...,String("9")) as well :) +func Digit() P { + accept := Accept(1) + return func(s string) (N, string) { + n, r := accept(s) + if !n.Matched { + return n, s + } + if n.Content[0] >= 48 && n.Content[0] <= 57 { + return n, r } return N{Matched: false, Content: "", Nodes: []N{n}}, s } } Index: src/0dev.org/parse/parse_test.go ================================================================== --- src/0dev.org/parse/parse_test.go +++ src/0dev.org/parse/parse_test.go @@ -74,5 +74,15 @@ } if n, r := s("ab"); n.Matched || n.Content != "" || n.Nodes == nil || r != "ab" { t.Error("Invalid result for String no-match test", n, r, len(r)) } } + +func TestDigit(t *testing.T) { + d := Digit() + if n, r := d("a"); n.Matched || n.Content != "" || n.Nodes == nil || r != "a" { + t.Error("Invalid result for Digit no-match test", n) + } + if n, r := d("1"); !n.Matched || n.Content != "1" || n.Nodes != nil || r != "" { + t.Error("Invalid result for Digit match test", n) + } +}