Push and Pop added

This commit is contained in:
milarin
2023-08-07 19:51:10 +02:00
parent 25505b0ea2
commit af840a5019
4 changed files with 62 additions and 14 deletions

View File

@ -6,19 +6,24 @@ import (
"strings"
"git.milar.in/milarin/ds"
"git.milar.in/milarin/slices"
)
type Reader struct {
buf ds.Stack[posRune]
src *bufio.Reader
pos *Position
buf ds.Stack[posRune]
indices ds.Stack[uint64]
index uint64
src *bufio.Reader
pos *Position
}
func New(r io.Reader) *Reader {
return &Reader{
buf: ds.NewArrayStack[posRune](),
src: bufio.NewReader(r),
pos: &Position{Index: 0, Line: 1, Column: 1},
buf: ds.NewArrayStack[posRune](),
src: bufio.NewReader(r),
pos: &Position{Index: 0, Line: 1, Column: 1},
index: 0,
indices: ds.NewArrayStack[uint64](),
}
}
@ -43,6 +48,7 @@ func (r *Reader) Rune() (rune, error) {
if err == nil {
r.buf.Push(r.psrn(rn))
r.pos.Advance(rn)
r.index++
}
return rn, err
}
@ -99,6 +105,8 @@ func (r *Reader) UnreadRune() error {
r.src = prependRune(rn.Rune, r.src)
}
r.index--
return nil
}
@ -250,8 +258,44 @@ func (r *Reader) ExpectOneOfString(str ...string) (string, bool, error) {
return "", false, nil
}
// Commit clears the internal buffer and therefore removes all data which were already read.
// After calling Commit any unreads will return ErrNothingToUnread until another read occured.
func (r *Reader) Commit() {
r.buf.Clear()
func (r *Reader) Push() {
r.indices.Push(r.index)
}
func (r *Reader) Pop() ([]rune, error) {
if r.indices.Empty() {
return nil, ErrPopFailed.New()
}
lastIndex := r.indices.Pop()
currentIndex := r.index
if lastIndex < currentIndex {
values := make([]rune, 0, int(currentIndex-lastIndex))
for i := 0; i < int(currentIndex-lastIndex); i++ {
err := r.UnreadRune()
if err != nil {
return nil, err
}
value, err := r.PeekRune()
if err != nil {
return nil, err
}
values = append(values, value)
}
return slices.Reverse(values), nil
} else if lastIndex > currentIndex {
values := make([]rune, 0, int(lastIndex-currentIndex))
for i := 0; i < int(lastIndex-currentIndex); i++ {
value, err := r.Rune()
if err != nil {
return nil, err
}
values = append(values, value)
}
return values, nil
}
return []rune{}, nil
}