Hey! I'm looking for decent ways to implement a parser and, in particular, the peek function seems, well, kind of hard to implement in rust.
I have the following (a reduced example)
enum Token {
Num(String),
Plus,
Minux,
LParen,
RParen,
}
enum BinOp {
Add,
Minus,
}
enum Expr {
Binary {
op: BinOp,
left: Box<Expr>,
right: Box<Expr>,
},
Num(i64),
}
struct Parser {
current: usize,
tokens: Vec<Token>,
}
And if I want to implement a peek function, I'd like to just get a reference to the token
impl Parser {
fn peek(self) -> Result<&Token, ()) {
let next: usize = self.current + 1;
let token = self.tokens.get(next);
match token {
Some(token) => Ok(token),
None => Err(()),
}
}
}
I get the following error:
error[E0106]: missing lifetime specifier
--> src\main.rs:32:29
|
32 | fn peek(self) -> Result<&Token, ()> {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
|
32 | fn peek(self) -> Result<&'static Token, ()> {
| +++++++
help: instead, you are more likely to want to change the argument to be borrowed...
|
32 | fn peek(&self) -> Result<&Token, ()> {
| +
help: ...or alternatively, you might want to return an owned value
|
32 - fn peek(self) -> Result<&Token, ()> {
32 + fn peek(self) -> Result<Token, ()> {
and this is a great error message, but the lifetimes are going over my head, but if I choose to return
an owned value, I need top implement the clone or copy (at time of writing, I had thought I had to implement both copy and clone)
I believe this works:
impl Parser {
fn peek(self) -> Result<Token, ()> {
let next: usize = self.current + 1;
let token = self.tokens.get(next);
match token {
Some(token) => Ok(token.clone()),
None => Err(()),
}
}
}
However, if I choose to implement copy for these types, I get variations of:
error[E0204]: the trait `Copy` cannot be implemented for this type
--> src\main.rs:4:6
|
3 | #[derive(Clone, Copy)]
| ---- in this derive macro expansion
4 | enum Token {
| ^^^^^
5 | Num(String),
| ------ this field does not implement `Copy`
Which I don't fully understand if I could fix because I don't have contorl over what String or Box could implement.
The more fundamental issue is that there's gaps in my knowledge and I'd like to address them. They seem to be:
- lifetimes
- implementing traits
- borrowing stuff
- copy stuff?
Could someone point me to a resource that would help alleviate gaps in my knowledge? I'm in a "I don't know what I don't know" predicament.
TIA!