Commit 68e25051 authored by Rob Pike's avatar Rob Pike

make a simpler regexp implementation with fewer dependencies and put it inside testing.

remove "regexp." from regexp tests.

R=rsc
DELTA=1173  (1152 added, 1 deleted, 20 changed)
OCL=33028
CL=33037
parent d08f0067
......@@ -37,18 +37,18 @@ type stringError struct {
err os.Error;
}
var bad_re = []stringError{
stringError{ `*`, regexp.ErrBareClosure },
stringError{ `(abc`, regexp.ErrUnmatchedLpar },
stringError{ `abc)`, regexp.ErrUnmatchedRpar },
stringError{ `x[a-z`, regexp.ErrUnmatchedLbkt },
stringError{ `abc]`, regexp.ErrUnmatchedRbkt },
stringError{ `[z-a]`, regexp.ErrBadRange },
stringError{ `abc\`, regexp.ErrExtraneousBackslash },
stringError{ `a**`, regexp.ErrBadClosure },
stringError{ `a*+`, regexp.ErrBadClosure },
stringError{ `a??`, regexp.ErrBadClosure },
stringError{ `*`, regexp.ErrBareClosure },
stringError{ `\x`, regexp.ErrBadBackslash },
stringError{ `*`, ErrBareClosure },
stringError{ `(abc`, ErrUnmatchedLpar },
stringError{ `abc)`, ErrUnmatchedRpar },
stringError{ `x[a-z`, ErrUnmatchedLbkt },
stringError{ `abc]`, ErrUnmatchedRbkt },
stringError{ `[z-a]`, ErrBadRange },
stringError{ `abc\`, ErrExtraneousBackslash },
stringError{ `a**`, ErrBadClosure },
stringError{ `a*+`, ErrBadClosure },
stringError{ `a??`, ErrBadClosure },
stringError{ `*`, ErrBareClosure },
stringError{ `\x`, ErrBadBackslash },
}
type vec []int;
......@@ -88,8 +88,8 @@ var matches = []tester {
tester{ `a*(|(b))c*`, "aacc", vec{0,4, 2,2, -1,-1} },
}
func compileTest(t *testing.T, expr string, error os.Error) *regexp.Regexp {
re, err := regexp.Compile(expr);
func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
re, err := Compile(expr);
if err != error {
t.Error("compiling `", expr, "`; unexpected error: ", err.String());
}
......
......@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# DO NOT EDIT. Automatically generated by gobuild.
# gobuild -m >Makefile
......@@ -20,7 +21,7 @@ test: packages
coverage: packages
gotest
6cov -g `pwd` | grep -v '_test\.go:'
6cov -g $$(pwd) | grep -v '_test\.go:'
%.$O: %.go
$(GC) -I_obj $*.go
......@@ -32,16 +33,23 @@ coverage: packages
$(AS) $*.s
O1=\
regexp.$O\
O2=\
testing.$O\
phases: a1
phases: a1 a2
_obj$D/testing.a: phases
a1: $(O1)
$(AR) grc _obj$D/testing.a testing.$O
$(AR) grc _obj$D/testing.a regexp.$O
rm -f $(O1)
a2: $(O2)
$(AR) grc _obj$D/testing.a testing.$O
rm -f $(O2)
newpkg: clean
mkdir -p _obj$D
......@@ -49,6 +57,7 @@ newpkg: clean
$(O1): newpkg
$(O2): a1
$(O3): a2
nuke: clean
rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/testing.a
......
This diff is collapsed.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package testing
import (
"strings";
"testing";
)
var good_re = []string{
``,
`.`,
`^.$`,
`a`,
`a*`,
`a+`,
`a?`,
`a|b`,
`a*|b*`,
`(a*|b)(c*|d)`,
`[a-z]`,
`[a-abc-c\-\]\[]`,
`[a-z]+`,
`[]`,
`[abc]`,
`[^1234]`,
`[^\n]`,
}
// TODO: nice to do this with a map
type stringError struct {
re string;
err string;
}
var bad_re = []stringError{
stringError{ `*`, ErrBareClosure },
stringError{ `(abc`, ErrUnmatchedLpar },
stringError{ `abc)`, ErrUnmatchedRpar },
stringError{ `x[a-z`, ErrUnmatchedLbkt },
stringError{ `abc]`, ErrUnmatchedRbkt },
stringError{ `[z-a]`, ErrBadRange },
stringError{ `abc\`, ErrExtraneousBackslash },
stringError{ `a**`, ErrBadClosure },
stringError{ `a*+`, ErrBadClosure },
stringError{ `a??`, ErrBadClosure },
stringError{ `*`, ErrBareClosure },
stringError{ `\x`, ErrBadBackslash },
}
type vec []int;
type tester struct {
re string;
text string;
match vec;
}
var matches = []tester {
tester{ ``, "", vec{0,0} },
tester{ `a`, "a", vec{0,1} },
tester{ `x`, "y", vec{} },
tester{ `b`, "abc", vec{1,2} },
tester{ `.`, "a", vec{0,1} },
tester{ `.*`, "abcdef", vec{0,6} },
tester{ `^abcd$`, "abcd", vec{0,4} },
tester{ `^bcd'`, "abcdef", vec{} },
tester{ `^abcd$`, "abcde", vec{} },
tester{ `a+`, "baaab", vec{1,4} },
tester{ `a*`, "baaab", vec{0,0} },
tester{ `[a-z]+`, "abcd", vec{0,4} },
tester{ `[^a-z]+`, "ab1234cd", vec{2,6} },
tester{ `[a\-\]z]+`, "az]-bcz", vec{0,4} },
tester{ `[^\n]+`, "abcd\n", vec{0,4} },
tester{ `[日本語]+`, "日本語日本語", vec{0,18} },
tester{ `()`, "", vec{0,0, 0,0} },
tester{ `(a)`, "a", vec{0,1, 0,1} },
tester{ `(.)(.)`, "日a", vec{0,4, 0,3, 3,4} },
tester{ `(.*)`, "", vec{0,0, 0,0} },
tester{ `(.*)`, "abcd", vec{0,4, 0,4} },
tester{ `(..)(..)`, "abcd", vec{0,4, 0,2, 2,4} },
tester{ `(([^xyz]*)(d))`, "abcd", vec{0,4, 0,4, 0,3, 3,4} },
tester{ `((a|b|c)*(d))`, "abcd", vec{0,4, 0,4, 2,3, 3,4} },
tester{ `(((a|b|c)*)(d))`, "abcd", vec{0,4, 0,4, 0,3, 2,3, 3,4} },
tester{ `a*(|(b))c*`, "aacc", vec{0,4, 2,2, -1,-1} },
}
func compileTest(t *testing.T, expr string, error string) *Regexp {
re, err := CompileRegexp(expr);
if err != error {
t.Error("compiling `", expr, "`; unexpected error: ", err);
}
return re
}
func printVec(t *testing.T, m []int) {
l := len(m);
if l == 0 {
t.Log("\t<no match>");
} else {
for i := 0; i < l; i = i+2 {
t.Log("\t", m[i], ",", m[i+1])
}
}
}
func printStrings(t *testing.T, m []string) {
l := len(m);
if l == 0 {
t.Log("\t<no match>");
} else {
for i := 0; i < l; i = i+2 {
t.Logf("\t%q", m[i])
}
}
}
func printBytes(t *testing.T, b [][]byte) {
l := len(b);
if l == 0 {
t.Log("\t<no match>");
} else {
for i := 0; i < l; i = i+2 {
t.Logf("\t%q", b[i])
}
}
}
func equal(m1, m2 []int) bool {
l := len(m1);
if l != len(m2) {
return false
}
for i := 0; i < l; i++ {
if m1[i] != m2[i] {
return false
}
}
return true
}
func equalStrings(m1, m2 []string) bool {
l := len(m1);
if l != len(m2) {
return false
}
for i := 0; i < l; i++ {
if m1[i] != m2[i] {
return false
}
}
return true
}
func equalBytes(m1 [][]byte, m2 []string) bool {
l := len(m1);
if l != len(m2) {
return false
}
for i := 0; i < l; i++ {
if string(m1[i]) != m2[i] {
return false
}
}
return true
}
func executeTest(t *testing.T, expr string, str string, match []int) {
re := compileTest(t, expr, "");
if re == nil {
return
}
m := re.ExecuteString(str);
if !equal(m, match) {
t.Error("ExecuteString failure on `", expr, "` matching `", str, "`:");
printVec(t, m);
t.Log("should be:");
printVec(t, match);
}
// now try bytes
m = re.Execute(strings.Bytes(str));
if !equal(m, match) {
t.Error("Execute failure on `", expr, "` matching `", str, "`:");
printVec(t, m);
t.Log("should be:");
printVec(t, match);
}
}
func TestGoodCompile(t *testing.T) {
for i := 0; i < len(good_re); i++ {
compileTest(t, good_re[i], "");
}
}
func TestBadCompile(t *testing.T) {
for i := 0; i < len(bad_re); i++ {
compileTest(t, bad_re[i].re, bad_re[i].err)
}
}
func TestExecute(t *testing.T) {
for i := 0; i < len(matches); i++ {
test := &matches[i];
executeTest(t, test.re, test.text, test.match)
}
}
func matchTest(t *testing.T, expr string, str string, match []int) {
re := compileTest(t, expr, "");
if re == nil {
return
}
m := re.MatchString(str);
if m != (len(match) > 0) {
t.Error("MatchString failure on `", expr, "` matching `", str, "`:", m, "should be", len(match) > 0);
}
// now try bytes
m = re.Match(strings.Bytes(str));
if m != (len(match) > 0) {
t.Error("Match failure on `", expr, "` matching `", str, "`:", m, "should be", len(match) > 0);
}
}
func TestMatch(t *testing.T) {
for i := 0; i < len(matches); i++ {
test := &matches[i];
matchTest(t, test.re, test.text, test.match)
}
}
func matchStringsTest(t *testing.T, expr string, str string, match []int) {
re := compileTest(t, expr, "");
if re == nil {
return
}
strs := make([]string, len(match)/2);
for i := 0; i < len(match); i++ {
strs[i/2] = str[match[i] : match[i+1]]
}
m := re.MatchStrings(str);
if !equalStrings(m, strs) {
t.Error("MatchStrings failure on `", expr, "` matching `", str, "`:");
printStrings(t, m);
t.Log("should be:");
printStrings(t, strs);
}
// now try bytes
s := re.MatchSlices(strings.Bytes(str));
if !equalBytes(s, strs) {
t.Error("MatchSlices failure on `", expr, "` matching `", str, "`:");
printBytes(t, s);
t.Log("should be:");
printStrings(t, strs);
}
}
func TestMatchStrings(t *testing.T) {
for i := 0; i < len(matches); i++ {
test := &matches[i];
matchTest(t, test.re, test.text, test.match)
}
}
func matchFunctionTest(t *testing.T, expr string, str string, match []int) {
m, err := MatchString(expr, str);
if err == "" {
return
}
if m != (len(match) > 0) {
t.Error("function Match failure on `", expr, "` matching `", str, "`:", m, "should be", len(match) > 0);
}
}
func TestMatchFunction(t *testing.T) {
for i := 0; i < len(matches); i++ {
test := &matches[i];
matchFunctionTest(t, test.re, test.text, test.match)
}
}
......@@ -15,8 +15,8 @@ import (
"flag";
"fmt";
"os";
"regexp";
"runtime";
"testing";
)
// Report as tests are run; default is silent for success.
......@@ -122,9 +122,9 @@ func Main(tests []Test) {
if len(tests) == 0 {
println("testing: warning: no tests to run");
}
re, err := regexp.Compile(*match);
if err != nil {
println("invalid regexp for -match:", err.String());
re, err := CompileRegexp(*match);
if err != "" {
println("invalid regexp for -match:", err);
os.Exit(1);
}
for i := 0; i < len(tests); i++ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment