Skip to content

Commit

Permalink
Allow custom types to be used for Pos, EndPos and Token.
Browse files Browse the repository at this point in the history
Specifically, these fields can now be of any type that is convertible
from the internal Participle types.
  • Loading branch information
alecthomas committed Mar 24, 2023
1 parent 4ddfe8b commit f07d82d
Show file tree
Hide file tree
Showing 3 changed files with 256 additions and 231 deletions.
8 changes: 5 additions & 3 deletions README.md
Expand Up @@ -596,13 +596,15 @@ There are a few areas where Participle can provide useful feedback to users of y
1. Of type [Error](https://pkg.go.dev/github.com/alecthomas/participle/v2#Error). This will contain positional information where available.
2. May either be [ParseError](https://pkg.go.dev/github.com/alecthomas/participle/v2#ParseError) or [lexer.Error](https://pkg.go.dev/github.com/alecthomas/participle/v2/lexer#Error)
2. Participle will make a best effort to return as much of the AST up to the error location as possible.
3. Any node in the AST containing a field `Pos lexer.Position` will be automatically
3. Any node in the AST containing a field `Pos lexer.Position` [^1] will be automatically
populated from the nearest matching token.
4. Any node in the AST containing a field `EndPos lexer.Position` will be
4. Any node in the AST containing a field `EndPos lexer.Position` [^1] will be
automatically populated from the token at the end of the node.
5. Any node in the AST containing a field `Tokens []lexer.Token` will be automatically
5. Any node in the AST containing a field `Tokens []lexer.Token` [^1] will be automatically
populated with _all_ tokens captured by the node, _including_ elided tokens.

[^1]: Either the concrete type or a type convertible to it, allowing user defined types to be used.

These related pieces of information can be combined to provide fairly comprehensive error reporting.

## Comments
Expand Down
10 changes: 6 additions & 4 deletions nodes.go
Expand Up @@ -131,11 +131,11 @@ func newStrct(typ reflect.Type) *strct {
usages: 1,
}
field, ok := typ.FieldByName("Pos")
if ok && field.Type == positionType {
if ok && positionType.ConvertibleTo(field.Type) {
s.posFieldIndex = field.Index
}
field, ok = typ.FieldByName("EndPos")
if ok && field.Type == positionType {
if ok && positionType.ConvertibleTo(field.Type) {
s.endPosFieldIndex = field.Index
}
field, ok = typ.FieldByName("Tokens")
Expand Down Expand Up @@ -172,14 +172,16 @@ func (s *strct) maybeInjectStartToken(token *lexer.Token, v reflect.Value) {
if s.posFieldIndex == nil {
return
}
v.FieldByIndex(s.posFieldIndex).Set(reflect.ValueOf(token.Pos))
f := v.FieldByIndex(s.posFieldIndex)
f.Set(reflect.ValueOf(token.Pos).Convert(f.Type()))
}

func (s *strct) maybeInjectEndToken(token *lexer.Token, v reflect.Value) {
if s.endPosFieldIndex == nil {
return
}
v.FieldByIndex(s.endPosFieldIndex).Set(reflect.ValueOf(token.Pos))
f := v.FieldByIndex(s.endPosFieldIndex)
f.Set(reflect.ValueOf(token.Pos).Convert(f.Type()))
}

func (s *strct) maybeInjectTokens(tokens []lexer.Token, v reflect.Value) {
Expand Down

0 comments on commit f07d82d

Please sign in to comment.