@@ -49,15 +49,15 @@ func NewParserError(highlight []byte, format string, args ...interface{}) error
4949// For performance reasons, go-toml doesn't make a copy of the input bytes to
5050// the parser. Make sure to copy all the bytes you need to outlive the slice
5151// given to the parser.
52- //
53- // The parser doesn't provide nodes for comments yet, nor for whitespace.
5452type Parser struct {
5553 data []byte
5654 builder builder
5755 ref reference
5856 left []byte
5957 err error
6058 first bool
59+
60+ KeepComments bool
6161}
6262
6363// Data returns the slice provided to the last call to Reset.
@@ -142,6 +142,44 @@ func (p *Parser) Error() error {
142142 return p .err
143143}
144144
145+ // Position describes a position in the input.
146+ type Position struct {
147+ // Number of bytes from the beginning of the input.
148+ Offset int
149+ // Line number, starting at 1.
150+ Line int
151+ // Column number, starting at 1.
152+ Column int
153+ }
154+
155+ // Shape describes the position of a range in the input.
156+ type Shape struct {
157+ Start Position
158+ End Position
159+ }
160+
161+ func (p * Parser ) position (b []byte ) Position {
162+ offset := danger .SubsliceOffset (p .data , b )
163+
164+ lead := p .data [:offset ]
165+
166+ return Position {
167+ Offset : offset ,
168+ Line : bytes .Count (lead , []byte {'\n' }) + 1 ,
169+ Column : len (lead ) - bytes .LastIndex (lead , []byte {'\n' }),
170+ }
171+ }
172+
173+ // Shape returns the shape of the given range in the input. Will
174+ // panic if the range is not a subslice of the input.
175+ func (p * Parser ) Shape (r Range ) Shape {
176+ raw := p .Raw (r )
177+ return Shape {
178+ Start : p .position (raw ),
179+ End : p .position (raw [r .Length :]),
180+ }
181+ }
182+
145183func (p * Parser ) parseNewline (b []byte ) ([]byte , error ) {
146184 if b [0 ] == '\n' {
147185 return b [1 :], nil
@@ -155,6 +193,19 @@ func (p *Parser) parseNewline(b []byte) ([]byte, error) {
155193 return nil , NewParserError (b [0 :1 ], "expected newline but got %#U" , b [0 ])
156194}
157195
196+ func (p * Parser ) parseComment (b []byte ) (reference , []byte , error ) {
197+ ref := invalidReference
198+ data , rest , err := scanComment (b )
199+ if p .KeepComments && err == nil {
200+ ref = p .builder .Push (Node {
201+ Kind : Comment ,
202+ Raw : p .Range (data ),
203+ Data : data ,
204+ })
205+ }
206+ return ref , rest , err
207+ }
208+
158209func (p * Parser ) parseExpression (b []byte ) (reference , []byte , error ) {
159210 // expression = ws [ comment ]
160211 // expression =/ ws keyval ws [ comment ]
@@ -168,7 +219,7 @@ func (p *Parser) parseExpression(b []byte) (reference, []byte, error) {
168219 }
169220
170221 if b [0 ] == '#' {
171- _ , rest , err := scanComment (b )
222+ ref , rest , err := p . parseComment (b )
172223 return ref , rest , err
173224 }
174225
@@ -190,7 +241,10 @@ func (p *Parser) parseExpression(b []byte) (reference, []byte, error) {
190241 b = p .parseWhitespace (b )
191242
192243 if len (b ) > 0 && b [0 ] == '#' {
193- _ , rest , err := scanComment (b )
244+ cref , rest , err := p .parseComment (b )
245+ if cref != invalidReference {
246+ p .builder .Chain (ref , cref )
247+ }
194248 return ref , rest , err
195249 }
196250
@@ -471,17 +525,33 @@ func (p *Parser) parseValArray(b []byte) (reference, []byte, error) {
471525 Kind : Array ,
472526 })
473527
528+ // First indicates whether the parser is looking for the first element
529+ // (non-comment) of the array.
474530 first := true
475531
476- var lastChild reference
532+ lastChild := invalidReference
533+
534+ addChild := func (valueRef reference ) {
535+ if lastChild == invalidReference {
536+ p .builder .AttachChild (parent , valueRef )
537+ } else {
538+ p .builder .Chain (lastChild , valueRef )
539+ }
540+ lastChild = valueRef
541+ }
477542
478543 var err error
479544 for len (b ) > 0 {
480- b , err = p .parseOptionalWhitespaceCommentNewline (b )
545+ cref := invalidReference
546+ cref , b , err = p .parseOptionalWhitespaceCommentNewline (b )
481547 if err != nil {
482548 return parent , nil , err
483549 }
484550
551+ if cref != invalidReference {
552+ addChild (cref )
553+ }
554+
485555 if len (b ) == 0 {
486556 return parent , nil , NewParserError (arrayStart [:1 ], "array is incomplete" )
487557 }
@@ -496,10 +566,13 @@ func (p *Parser) parseValArray(b []byte) (reference, []byte, error) {
496566 }
497567 b = b [1 :]
498568
499- b , err = p .parseOptionalWhitespaceCommentNewline (b )
569+ cref , b , err = p .parseOptionalWhitespaceCommentNewline (b )
500570 if err != nil {
501571 return parent , nil , err
502572 }
573+ if cref != invalidReference {
574+ addChild (cref )
575+ }
503576 } else if ! first {
504577 return parent , nil , NewParserError (b [0 :1 ], "array elements must be separated by commas" )
505578 }
@@ -515,17 +588,16 @@ func (p *Parser) parseValArray(b []byte) (reference, []byte, error) {
515588 return parent , nil , err
516589 }
517590
518- if first {
519- p .builder .AttachChild (parent , valueRef )
520- } else {
521- p .builder .Chain (lastChild , valueRef )
522- }
523- lastChild = valueRef
591+ addChild (valueRef )
524592
525- b , err = p .parseOptionalWhitespaceCommentNewline (b )
593+ cref , b , err = p .parseOptionalWhitespaceCommentNewline (b )
526594 if err != nil {
527595 return parent , nil , err
528596 }
597+ if cref != invalidReference {
598+ addChild (cref )
599+ }
600+
529601 first = false
530602 }
531603
@@ -534,15 +606,34 @@ func (p *Parser) parseValArray(b []byte) (reference, []byte, error) {
534606 return parent , rest , err
535607}
536608
537- func (p * Parser ) parseOptionalWhitespaceCommentNewline (b []byte ) ([]byte , error ) {
609+ func (p * Parser ) parseOptionalWhitespaceCommentNewline (b []byte ) (reference , []byte , error ) {
610+ rootCommentRef := invalidReference
611+ latestCommentRef := invalidReference
612+
613+ addComment := func (ref reference ) {
614+ if rootCommentRef == invalidReference {
615+ rootCommentRef = ref
616+ } else if latestCommentRef == invalidReference {
617+ p .builder .AttachChild (rootCommentRef , ref )
618+ latestCommentRef = ref
619+ } else {
620+ p .builder .Chain (latestCommentRef , ref )
621+ latestCommentRef = ref
622+ }
623+ }
624+
538625 for len (b ) > 0 {
539626 var err error
540627 b = p .parseWhitespace (b )
541628
542629 if len (b ) > 0 && b [0 ] == '#' {
543- _ , b , err = scanComment (b )
630+ var ref reference
631+ ref , b , err = p .parseComment (b )
544632 if err != nil {
545- return nil , err
633+ return invalidReference , nil , err
634+ }
635+ if ref != invalidReference {
636+ addComment (ref )
546637 }
547638 }
548639
@@ -553,14 +644,14 @@ func (p *Parser) parseOptionalWhitespaceCommentNewline(b []byte) ([]byte, error)
553644 if b [0 ] == '\n' || b [0 ] == '\r' {
554645 b , err = p .parseNewline (b )
555646 if err != nil {
556- return nil , err
647+ return invalidReference , nil , err
557648 }
558649 } else {
559650 break
560651 }
561652 }
562653
563- return b , nil
654+ return rootCommentRef , b , nil
564655}
565656
566657func (p * Parser ) parseMultilineLiteralString (b []byte ) ([]byte , []byte , []byte , error ) {
0 commit comments