Hello, I'm writing a Parser for a programming language (this is for practice, I know parser generators exist haha)
Here's a simplified version of my parser:
type ParseFn<'b, T> = dyn Fn(&mut T) -> Expression<'b>;
struct Parser<'a, 'b: 'a> {
l: &'a mut Lexer<'b>,
errors: Vec<String>,
curr_token: Option<Token<'b>>,
peek_token: Option<Token<'b>>,
prefix_parse_fns: HashMap<TokenType, Box<ParseFn<'b, Parser<'a, 'b>>>>,
infix_parse_fns: HashMap<TokenType, Box<ParseFn<'b, Parser<'a, 'b>>>>,
}
In the new()
function of my Parser, I'm registering a function which is one of the parser's own methods:
impl<'a, 'b: 'a> Parser<'a, 'b> {
fn new(l: &'a mut Lexer<'b>) -> Parser<'a, 'b> {
let curr_token = Some(l.next_token());
let peek_token = Some(l.next_token());
let mut p = Parser {
l,
errors: Vec::new(),
curr_token,
peek_token,
prefix_parse_fns: Default::default(),
infix_parse_fns: Default::default(),
};
p.register_prefix(IDENT, Box::new(&Parser::parse_identifier));
p
}
fn register_prefix(&mut self, token: TokenType, func: Box<ParseFn<'b, Parser<'a, 'b>>>) {
self.prefix_parse_fns.insert(token, func);
}
fn parse_identifier(&mut self) -> Expression<'b> {
Identifier(self.curr_token.take().unwrap())
}
// other code
In one of my functions I decide to parse the next statement based on the current token that I'm reading:
fn parse_statement(&mut self) -> Option<Statement<'b>> {
match self.curr_token.as_ref().unwrap().token_type {
TokenType::LET => self.parse_let_statement(),
TokenType::RETURN => self.parse_return_statement(),
_ => self.parse_expression_statement(),
}
}
fn parse_expression_statement(&mut self) -> Option<Statement<'b>> {
let expression = self.parse_expression(Precedence::Lowest);
if expression.is_none() {
return None;
}
let expression = expression.unwrap();
if self.peek_token_is(SEMICOLON) {
self.next_token();
}
return Some(ExpressionStatement { expression });
}
fn parse_expression(&mut self, precedence: Precedence) -> Option<Expression<'b>> {
let curr_type = &self.curr_token.as_ref().unwrap().token_type;
let prefix_parser = self
.prefix_parse_fns
.get(curr_type)
.unwrap()
.as_ref();
Some(prefix_parser(self))
}
And the parse_identifier
function is defined above underneath the new()
definition.
I'm currently getting this error:
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> parser/src/parser.rs:81:14
|
76 | let prefix_parser = self
| _____________________________-
77 | | .prefix_parse_fns
78 | | .get(curr_type)
| |___________________________- immutable borrow occurs here
...
81 | Some(prefix_parser(self))
| -------------^^^^^^
| |
| mutable borrow occurs here
| immutable borrow later used by call
How can I write this in a rust
-y way? I'm following along with a book that's implemented this in Go, but I'm trying to capture the same behaviour in Rust.
Thanks in advance,
Arshan