{ Name: "Firefox", Version: Version{ Text: "31.0", }, }, }, }, } var _ = gspec.Add(func(s gspec.S) { testcase := s.Alias("testcase:") expect := gspec.Expect(s.FailNow) for i, tc := range testcases { testcase(strconv.Itoa(i), func() { r, err := ParseUserAgent(tc.str) expect(err).Equal(nil) expect(r).Equal(tc.ua) }) } }) func TestAll(t *testing.T) { gspec.Test(t) } func init() { gspec.SetSprint(flowPrint) } func flowPrint(v interface{}) string {
var _ = gspec.Add(func(s gspec.S) { describe, given, it, they, and := gspec.Alias5("describe", "given", "it", "they", "and", s) expect := gspec.Expect(s.FailNow) describe("patterns", func() { given("a pattern", func() { a := Pat("ab") it("can be repeated zero or one time", func() { expect(a.ZeroOrOne().String()).Equal("(?:ab)?") }) it("can be repeated zero or more times", func() { expect(a.ZeroOrMore().String()).Equal("(?:ab)*") }) it("can be repeated one or more times", func() { expect(a.OneOrMore().String()).Equal("(?:ab)+") }) }) given("multiple patterns", func() { a, b, c := Pat("aa"), Pat("bb"), Pat("cc") they("can be concatenated into one pattern", func() { one := Con(a, b, c) expect(one.String()).Equal("aabbcc") }) they("can be alternative choices", func() { alt := Or(a, b, c) expect(alt.String()).Equal("aa|bb|cc") }) }) }) describe("character sets", func() { given("a character set", func() { c := Char(`abcde`) it("can be converted to a canonical pattern", func() { expect(c.String()).Equal(`[a-e]`) }) it("can be negated", func() { nc := c.Negate() expect(nc.String()).Equal(`[^a-e]`) and("the original pattern is not changed by the negation", func() { expect(c.String()).Equal(`[a-e]`) }) and("the negated pattern can be negated back", func() { expect(nc.Negate().String()).Equal(`[a-e]`) }) }) it("can exclude a subset", func() { expect(c.Exclude(Char(`bd`)).String()).Equal(`[ace]`) }) }) given("a character set with a single element (OpLiteral)", func() { a := Char(`a`) it("can be negated", func() { na := a.Negate() expect(na.String()).Equal(`[^a]`) expect(na.Negate().String()).Equal(`[a]`) }) }) given("a character set with an letter of upper and lower case (OpLiteral)", func() { x := Char(`xX`) it("has a canonical form of character set", func() { expect(x.String()).Equal(`[Xx]`) }) it("can be negated", func() { nx := x.Negate() expect(nx.String()).Equal(`[^Xx]`) expect(nx.Negate().String()).Equal(`[Xx]`) }) }) given("multiple character sets", func() { a := Char(`a`) mn := Char(`mn`) z := Char(`z`) they("can be merged into one character set", func() { one := Merge(a, mn, z) expect(one.String()).Equal(`[am-nz]`) }) }) }) describe("the scanner", func() { a := Char(`a`) s := Char(` `) b := Char(`b`) m := NewMatcher(a, s, b) scanner, _ := NewStringScanner(m, "b a") expect(scanner.Scan()).Equal(true) expect(scanner.Error()).Equal(nil) expect(scanner.Token()).Equal( &Token{ ID: 3, Value: []byte("b"), Pos: 0, }) expect(scanner.Scan()).Equal(true) expect(scanner.Error()).Equal(nil) expect(scanner.Token()).Equal( &Token{ ID: 2, Value: []byte(" "), Pos: 1, }) expect(scanner.Scan()).Equal(true) expect(scanner.Error()).Equal(nil) expect(scanner.Token()).Equal( &Token{ ID: 1, Value: []byte("a"), Pos: 2, }) expect(scanner.Scan()).Equal(true) expect(scanner.Error()).Equal(nil) expect(scanner.Token()).Equal( &Token{ ID: EOF, Value: nil, Pos: 3, }) expect(scanner.Scan()).Equal(false) expect(scanner.Error()).Equal(nil) }) })
var _ = gspec.Add(func(s gspec.S) { describe, testcase, given := gspec.Alias3("describe", "testcase:", "given", s) describe("the parser", func() { given("simple arithmetic grammar", func() { b := NewBuilder() Term, Or, Con := b.Term, b.Or, b.Con var ( T = Term("T") Plus = Term(`+`) Mult = Term(`*`) M = NewRule().As("M") _ = M.Define(Or( T, Con(M, Mult, T), )) S = NewRule().As("S") _ = S.Define(Or( Con(S, Plus, M), M, )) P = Con(S, EOF).As("P") ) P.InitTermSet() testcase("assotitivity", func() { testParse(s, P, TT{ tok("1", T), tok("+", Plus), tok("2", T), tok("+", Plus), tok("3", T), }, ` P ::= S EOF S ::= S + M S ::= S + M S ::= M M ::= T T ::= 1 + ::= + M ::= T T ::= 2 + ::= + M ::= T T ::= 3 EOF ::= `) }) testcase("precedence", func() { testParse(s, P, TT{ tok("2", T), tok("+", Plus), tok("3", T), tok("*", Mult), tok("4", T), }, ` P ::= S EOF S ::= S + M S ::= M M ::= T T ::= 2 + ::= + M ::= M * T M ::= T T ::= 3 * ::= * T ::= 4 EOF ::= `) }) }) given("a grammar with nullable rule", func() { b := NewBuilder() Term, Con, Or := b.Term, b.Con, b.Or var ( A = Term("A") B = Term("B") C = Term("C") P = Con(Or(Con(A, B), A).As("AX"), C, EOF).As("P") ) P.InitTermSet() testcase("a sequence without the optional token", func() { testParse(s, P, TT{ tok("A", A), tok("C", C), }, ` P ::= AX C EOF AX ::= A A ::= A C ::= C EOF ::= `, ) }) testcase("a sequence with the optional token", func() { testParse(s, P, TT{ tok("A", A), tok("B", B), tok("C", C), }, ` P ::= AX C EOF AX ::= A B A ::= A B ::= B C ::= C EOF ::= `) }) }) given("a grammar with zero or more repetition", func() { b := NewBuilder() Term, Con, Or := b.Term, b.Con, b.Or var ( A = Term("A") B = Term("B") X = B.AtLeast(1).As("X") C = Term("C") P = Con(A, Or(C, Con(X, C)).As("XC"), EOF).As("P") ) P.InitTermSet() testcase("zero", func() { testParse(s, P, TT{ tok("A", A), tok("C", C), }, ` P ::= A XC EOF A ::= A XC ::= C C ::= C EOF ::= `) }) testcase("one", func() { testParse(s, P, TT{ tok("A", A), tok("B", B), tok("C", C), }, ` P ::= A XC EOF A ::= A XC ::= X C X ::= B B ::= B C ::= C EOF ::= `) }) testcase("two", func() { testParse(s, P, TT{ tok("A", A), tok("B", B), tok("B", B), tok("C", C), }, ` P ::= A XC EOF A ::= A XC ::= X C X ::= B X B ::= B X ::= B B ::= B C ::= C EOF ::= `) }) }) given("a grammar with common prefix", func() { b := NewBuilder() Term, Or, Con := b.Term, b.Or, b.Con var ( A = Term("A") B = Term("B") X = Con(A).As("X") Y = Con(A, B).As("Y") S = Or(X, Y).As("S") P = Con(S, EOF).As("P") ) P.InitTermSet() testcase("short", func() { testParse(s, P, TT{ tok("A", A), }, ` P ::= S EOF S ::= X X ::= A EOF ::= `) }) testcase("short", func() { testParse(s, P, TT{ tok("A", A), tok("B", B), }, ` P ::= S EOF S ::= Y Y ::= X B X ::= A B ::= B EOF ::= `) }) }) }) })