diff --git a/bin/.go-1.16.4.pkg b/bin/.go@latest.pkg similarity index 100% rename from bin/.go-1.16.4.pkg rename to bin/.go@latest.pkg diff --git a/bin/go b/bin/go index 213f7236..142d6ff9 120000 --- a/bin/go +++ b/bin/go @@ -1 +1 @@ -.go-1.16.4.pkg \ No newline at end of file +.go@latest.pkg \ No newline at end of file diff --git a/bin/gofmt b/bin/gofmt index 213f7236..142d6ff9 120000 --- a/bin/gofmt +++ b/bin/gofmt @@ -1 +1 @@ -.go-1.16.4.pkg \ No newline at end of file +.go@latest.pkg \ No newline at end of file diff --git a/grammar.go b/grammar.go index fdec32f6..18d7545c 100644 --- a/grammar.go +++ b/grammar.go @@ -208,7 +208,7 @@ func (g *generatorContext) parseCapture(slexer *structLexer) (node, error) { return &capture{field, n}, nil } ft := indirectType(field.Type) - if ft.Kind() == reflect.Struct && ft != tokenType && ft != tokensType && !field.Type.Implements(captureType) && !field.Type.Implements(textUnmarshalerType) { + if ft.Kind() == reflect.Struct && ft != tokenType && ft != tokensType && !implements(ft, captureType) && !implements(ft, textUnmarshalerType) { return nil, fmt.Errorf("structs can only be parsed with @@ or by implementing the Capture or encoding.TextUnmarshaler interfaces") } n, err := g.parseTermNoModifiers(slexer, false) @@ -377,3 +377,7 @@ func indirectType(t reflect.Type) reflect.Type { } return t } + +func implements(t, i reflect.Type) bool { + return t.Implements(i) || reflect.PtrTo(t).Implements(i) +} diff --git a/parser_test.go b/parser_test.go index 3b5eb45d..51407bfe 100644 --- a/parser_test.go +++ b/parser_test.go @@ -1648,3 +1648,35 @@ func BenchmarkIssue143(b *testing.B) { } } } + +type Boxes struct { + Pos lexer.Position + Boxes Box `@Ident` +} + +type Box struct { + Pos lexer.Position + Val string `@Ident` +} + +func (b *Box) Capture(values []string) error { + b.Val = values[0] + return nil +} + +func TestBoxedCapture(t *testing.T) { + lex := stateful.MustSimple([]stateful.Rule{ + {"Ident", `[a-zA-Z](\w|\.|/|:|-)*`, nil}, + {"whitespace", `\s+`, nil}, + }) + + parser := participle.MustBuild(&Boxes{}, + participle.Lexer(lex), + participle.UseLookahead(2), + ) + + boxed := &Boxes{} + if err := parser.ParseString("test", "abc::cdef.abc", boxed); err != nil { + t.Fatal(err) + } +}