parsing modes
This commit is contained in:
parent
3b5bbb50d5
commit
7b33b0aa4a
@ -10,3 +10,4 @@
|
|||||||
- [RcChars](./exercises/rcchars.md)
|
- [RcChars](./exercises/rcchars.md)
|
||||||
- [Chapter 2](./chapter_2.md)
|
- [Chapter 2](./chapter_2.md)
|
||||||
- [AnyStr](./exercises/anystr.md)
|
- [AnyStr](./exercises/anystr.md)
|
||||||
|
- [Mode](./exercises/mode.md)
|
||||||
|
@ -1 +1 @@
|
|||||||
# Chapter 2
|
# Chapter 2: Missing Requirements
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# `AnyStr`?
|
||||||
|
|
||||||
Create something similar to [Python's `typing.AnyStr`].
|
Create something similar to [Python's `typing.AnyStr`].
|
||||||
|
|
||||||
[Python's `typing.AnyStr`]: https://docs.python.org/3/library/typing.html#typing.AnyStr
|
[Python's `typing.AnyStr`]: https://docs.python.org/3/library/typing.html#typing.AnyStr
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
Make `test_covariance` compile by making `BoolStream<'a>` covariant `'a`. Restrictions:
|
# Introducing variance to objects
|
||||||
|
|
||||||
|
Make `test_covariance` compile by making `BoolStream<'a>` covariant over `'a`. Restrictions:
|
||||||
- Can only change implementation details of `BoolStream` and its methods and add extra items outside of what's given, i.e. no signature/test change.
|
- Can only change implementation details of `BoolStream` and its methods and add extra items outside of what's given, i.e. no signature/test change.
|
||||||
- Changed version must behave the same way.
|
- Changed version must behave the same way as the original.
|
||||||
|
|
||||||
Consider the following code:
|
Consider the following code:
|
||||||
```rust,compile_fail
|
```rust,compile_fail
|
||||||
|
72
src/exercises/mode.md
Normal file
72
src/exercises/mode.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# Parsing modes
|
||||||
|
Merge implementations of `ConsumesStream` and `Deterministic` for tuple.
|
||||||
|
|
||||||
|
It's recommended to first solve [this exercise](./multiple_blanket.md).
|
||||||
|
|
||||||
|
```rust
|
||||||
|
trait Stream: Sized {
|
||||||
|
/// Try to read `n` bytes. Consumes the stream on failure.
|
||||||
|
fn read_n<A, E>(
|
||||||
|
self,
|
||||||
|
n: usize,
|
||||||
|
ok: impl FnOnce(&[u8]) -> A,
|
||||||
|
err: impl FnOnce(&[u8]) -> E,
|
||||||
|
) -> Result<(A, Self), E>;
|
||||||
|
|
||||||
|
/// Read all bytes, consuming the stream.
|
||||||
|
fn read_all<A>(self, ok: impl FnOnce(&[u8]) -> A) -> A;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Parsable: Sized {
|
||||||
|
type Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Can parse any length of data.
|
||||||
|
trait ConsumesStream: Parsable {
|
||||||
|
/// Try to parse the value. Can handle EOF, can ask for all data the stream has.
|
||||||
|
fn parse(stream: impl Stream) -> Result<Self, Self::Error>;
|
||||||
|
|
||||||
|
/// Push extra data into the value.
|
||||||
|
fn extend(self, data: &[u8]) -> Result<Self, Self::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the parsing is terminated, is only determined by the data already parsed.
|
||||||
|
trait Deterministic: Parsable {
|
||||||
|
/// Returns the stream, as it shouldn't succeed on unexpected EOF.
|
||||||
|
fn parse<S: Stream>(stream: S) -> Result<(Self, S), Self::Error>;
|
||||||
|
|
||||||
|
/// Always fail on extra data.
|
||||||
|
fn fail(data: &[u8]) -> Self::Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Either<L, R> {
|
||||||
|
Left(L),
|
||||||
|
Right(R),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Parsable, B: Parsable> Parsable for (A, B) {
|
||||||
|
type Error = Either<A::Error, B::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Deterministic, B: ConsumesStream> ConsumesStream for (A, B) {
|
||||||
|
fn parse(stream: impl Stream) -> Result<Self, Self::Error> {
|
||||||
|
let (a, stream) = A::parse(stream).map_err(Either::Left)?;
|
||||||
|
B::parse(stream).map_err(Either::Right).map(|b| (a, b))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extend(self, data: &[u8]) -> Result<Self, Self::Error> {
|
||||||
|
self.1.extend(data).map_err(Either::Right).map(|b| (self.0, b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: Deterministic, B: Deterministic> Deterministic for (A, B) {
|
||||||
|
fn parse<S: Stream>(stream: S) -> Result<(Self, S), Self::Error> {
|
||||||
|
let (a, stream) = A::parse(stream).map_err(Either::Left)?;
|
||||||
|
B::parse(stream).map_err(Either::Right).map(|(b, stream)| ((a, b), stream))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fail(data: &[u8]) -> Self::Error {
|
||||||
|
Either::Right(B::fail(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
@ -1,13 +1,14 @@
|
|||||||
|
# Blanket, blanket, blanket
|
||||||
Make this compile with the following restrictions:
|
Make this compile with the following restrictions:
|
||||||
- `A1` doesn't know about/depend on `A2`.
|
- **Can't edit definitions of `A`, `test`, `tes1`, `test2`; can only add code outside of those items.**
|
||||||
- `A2` doesn't know about/depend on `A1`.
|
|
||||||
- `A1` doesn't know about/depend on `A`.
|
|
||||||
- `A2` doesn't know about/depend on `A`.
|
|
||||||
- **Some types are `A1` but not `A2`.**
|
- **Some types are `A1` but not `A2`.**
|
||||||
- **Some types are `A2` but not `A1`.**
|
- **Some types are `A2` but not `A1`.**
|
||||||
- Some types are `A` but not `A2`.
|
- Some types are `A` but not `A2`.
|
||||||
- Some types are `A` but not `A1`.
|
- Some types are `A` but not `A1`.
|
||||||
- **Can't edit definitions of `A`, `test`, `tes1`, `test2`; can only add code outside of those items.**
|
- `A1` doesn't know about/depend on `A2`.
|
||||||
|
- `A2` doesn't know about/depend on `A1`.
|
||||||
|
- `A1` doesn't know about/depend on `A`.
|
||||||
|
- `A2` doesn't know about/depend on `A`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
trait A {
|
trait A {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# Owned [`Chars`]
|
||||||
|
|
||||||
[`Chars`] but keeping a strong reference ([`Rc`]) to the string.
|
[`Chars`] but keeping a strong reference ([`Rc`]) to the string.
|
||||||
|
|
||||||
[`Chars`]: https://doc.rust-lang.org/std/str/struct.Chars.html
|
[`Chars`]: https://doc.rust-lang.org/std/str/struct.Chars.html
|
||||||
@ -41,10 +43,10 @@
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Solutions
|
## Solutions
|
||||||
- [Solution] used in rattlescript.
|
- [Implementation] used in rattlescript.
|
||||||
- [Same solution] but with some extra comments.
|
- [Same solution] but with some extra comments.
|
||||||
- [Another solution].
|
- [Another solution].
|
||||||
|
|
||||||
[Solution]: https://github.com/HavenSelph/rattlescript/blob/f8bafb8b063b9bf056efb1ea14188db0624d981c/src/interpreter/value.rs#L21-L50
|
[Implementation]: https://github.com/HavenSelph/rattlescript/blob/f8bafb8b063b9bf056efb1ea14188db0624d981c/src/interpreter/value.rs#L21-L50
|
||||||
[Same solution]: https://gist.github.com/timotheyca/7e46c9734653b2fcbe826ea4d13b9aa0
|
[Same solution]: https://gist.github.com/timotheyca/7e46c9734653b2fcbe826ea4d13b9aa0
|
||||||
[Another solution]: https://gist.github.com/timotheyca/bc419e0997d6f7ea5722fd2823a78c62
|
[Another solution]: https://gist.github.com/timotheyca/bc419e0997d6f7ea5722fd2823a78c62
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
# Exercises
|
# Exercises
|
||||||
|
|
||||||
Random Rust exercises.
|
Random Rust exercises. Mostly typesystem-oriented.
|
||||||
|
|
||||||
**Warning: this is a live-edited website, errors and accidental spoilers are to be expected.**
|
**Warning if you're viewing this not on github.io: this is a live-edited website, errors and accidental spoilers are to be expected.**
|
||||||
|
|
||||||
# Solutions
|
# Solutions
|
||||||
|
|
||||||
Currently solutions are mostly provided in a non-human-readable form in the page source.
|
Presently, solutions are often provided in a non-human-readable (compacted+misformatted) form as hidden code.
|
||||||
Those are mostly intended for testing that the exercise is even possible to solve.
|
Those are intended for testing that the exercise is even possible to solve.
|
||||||
```rust
|
```rust
|
||||||
# /*
|
# /*
|
||||||
fn fix_me() { // Greyed out because the solution changes this line.
|
fn fix_me() { // Greyed out because the solution changes this line.
|
||||||
@ -19,7 +19,7 @@ fn do_not_change_this() {
|
|||||||
fixed_name()
|
fixed_name()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Some exercises may not include have the replaced parts greyed out:
|
Some exercises may not have the replaced parts greyed out:
|
||||||
```rust
|
```rust
|
||||||
# mod __ {
|
# mod __ {
|
||||||
fn fix_me() {
|
fn fix_me() {
|
||||||
|
Loading…
Reference in New Issue
Block a user