hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit e55a8339c2baca8c33a20b543cba5910b95ffa3c
parent 2f2a662f44bc948871ddaa2bea6f74da9a3ecbb2
Author: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Date:   Mon, 22 Feb 2021 20:46:18 +0100

strings/iter.ha: implement reverse iterator with prev()

and require strings::next() to be next operation after strings::push()

Diffstat:
Mstrings/iter.ha | 23++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/strings/iter.ha b/strings/iter.ha @@ -29,9 +29,22 @@ export fn next(iter: *iterator) (rune | void) = { }; }; +// Get the previous rune from an iterator, or void when at the start of the +// string. +export fn prev(iter: *iterator) (rune | void) = { + assert(iter.push is void); + return match (utf8::prev(&iter.dec)) { + r: rune => r, + void => void, + (utf8::more | utf8::invalid) => + abort("Invalid UTF-8 string (this should not happen)"), + }; +}; + + // Pushes a rune back to the iterator, effectively un-reading it. The given rune -// will be returned on the next call to 'next'. Only one rune can be pushed at a -// time. +// will be returned on the next call to 'next'. First operation on +// the iterator after pushing must be a next() call export fn push(iter: *iterator, r: rune) void = { assert(iter.push is void); iter.push = r; @@ -39,11 +52,13 @@ export fn push(iter: *iterator, r: rune) void = { // Return a substring from the next rune to the end of the string. export fn iter_str(iter: *iterator) str = { + assert(iter.push is void); return from_utf8(iter.dec.src[iter.dec.offs..]); }; @test fn iter() void = { let s = iter("こんにちは"); + assert(prev(&s) is void); const expected1 = ['こ', 'ん']; for (let i = 0z; i < len(expected1); i += 1) { match (next(&s)) { @@ -52,7 +67,8 @@ export fn iter_str(iter: *iterator) str = { }; }; assert(iter_str(&s) == "にちは"); - const expected2 = ['に', 'ち', 'は']; + assert(prev(&s) as rune == 'ん'); + const expected2 = ['ん', 'に', 'ち', 'は']; for (let i = 0z; i < len(expected2); i += 1) { match (next(&s)) { r: rune => assert(r == expected2[i]), @@ -63,4 +79,5 @@ export fn iter_str(iter: *iterator) str = { assert(next(&s) is void); push(&s, 'q'); assert(next(&s) as rune == 'q'); + assert(prev(&s) as rune == 'は'); };