positions introduced
This commit is contained in:
		
							
								
								
									
										6
									
								
								pos_rune.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								pos_rune.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | package bufr | ||||||
|  |  | ||||||
|  | type posRune struct { | ||||||
|  | 	Rune rune | ||||||
|  | 	Pos  Position | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								position.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								position.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | package bufr | ||||||
|  |  | ||||||
|  | type Position struct { | ||||||
|  | 	Index  int | ||||||
|  | 	Line   int | ||||||
|  | 	Column int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *Position) Advance(rn rune) { | ||||||
|  | 	p.Index++ | ||||||
|  | 	if rn == '\n' { | ||||||
|  | 		p.Line++ | ||||||
|  | 		p.Column = 0 | ||||||
|  | 	} else { | ||||||
|  | 		p.Column++ | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								reader.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								reader.go
									
									
									
									
									
								
							| @ -9,22 +9,36 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type Reader struct { | type Reader struct { | ||||||
| 	buf *dstruct.Stack[rune] | 	buf *dstruct.Stack[posRune] | ||||||
| 	src *bufio.Reader | 	src *bufio.Reader | ||||||
|  | 	pos *Position | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewReader(r io.Reader) *Reader { | func NewReader(r io.Reader) *Reader { | ||||||
| 	return &Reader{ | 	return &Reader{ | ||||||
| 		buf: new(dstruct.Stack[rune]), | 		buf: new(dstruct.Stack[posRune]), | ||||||
| 		src: bufio.NewReader(r), | 		src: bufio.NewReader(r), | ||||||
|  | 		pos: &Position{}, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (r *Reader) psrn(rn rune) posRune { | ||||||
|  | 	return posRune{ | ||||||
|  | 		Rune: rn, | ||||||
|  | 		Pos:  *r.pos, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Reader) Pos() (index, line, column int) { | ||||||
|  | 	return r.pos.Index, r.pos.Line, r.pos.Column | ||||||
|  | } | ||||||
|  |  | ||||||
| // Rune returns the next rune in r | // Rune returns the next rune in r | ||||||
| func (r *Reader) Rune() (rune, error) { | func (r *Reader) Rune() (rune, error) { | ||||||
| 	rn, _, err := r.src.ReadRune() | 	rn, _, err := r.src.ReadRune() | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		r.buf.Push(rn) | 		r.buf.Push(r.psrn(rn)) | ||||||
|  | 		r.pos.Advance(rn) | ||||||
| 	} | 	} | ||||||
| 	return rn, err | 	return rn, err | ||||||
| } | } | ||||||
| @ -38,9 +52,12 @@ func (r *Reader) UnreadRune() error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := r.src.UnreadRune(); err == nil { | 	if err := r.src.UnreadRune(); err == nil { | ||||||
| 		r.buf.Pop() | 		rn := r.buf.Pop() | ||||||
|  | 		*r.pos = rn.Pos | ||||||
| 	} else { | 	} else { | ||||||
| 		r.src = prependRune(r.buf.Pop(), r.src) | 		rn := r.buf.Pop() | ||||||
|  | 		*r.pos = rn.Pos | ||||||
|  | 		r.src = prependRune(rn.Rune, r.src) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
|  | |||||||
							
								
								
									
										24
									
								
								reader_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								reader_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | package bufr | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestPos(t *testing.T) { | ||||||
|  | 	r := NewReader(strings.NewReader("hello world\nsecond line")) | ||||||
|  |  | ||||||
|  | 	unread := false | ||||||
|  | 	for rn, err := r.Rune(); err == nil; rn, err = r.Rune() { | ||||||
|  | 		index, line, col := r.Pos() | ||||||
|  | 		fmt.Println(string(rn), index, line, col) | ||||||
|  |  | ||||||
|  | 		if !unread && rn == '\n' { | ||||||
|  | 			for i := 0; i < 5; i++ { | ||||||
|  | 				r.UnreadRune() | ||||||
|  | 			} | ||||||
|  | 			unread = true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Timon Ringwald
					Timon Ringwald