Parser - Support for calls with arbitrary expressions as the callee

This commit is contained in:
Emmanuel BENOîT 2023-01-02 15:32:33 +01:00
parent 4c55e9e784
commit fecea3b388

View file

@ -507,7 +507,7 @@ impl Parser {
/// ``` /// ```
/// unary := "-" unary /// unary := "-" unary
/// unary := "!" unary /// unary := "!" unary
/// unary := primary /// unary := primary call_arguments*
/// ``` /// ```
fn parse_unary(&mut self) -> ParserResult<ast::ExprNode> { fn parse_unary(&mut self) -> ParserResult<ast::ExprNode> {
if let Some(operator) = self.expect(&[TokenType::Bang, TokenType::Minus]) { if let Some(operator) = self.expect(&[TokenType::Bang, TokenType::Minus]) {
@ -516,7 +516,11 @@ impl Parser {
right: Box::new(self.parse_unary()?), right: Box::new(self.parse_unary()?),
}) })
} else { } else {
self.parse_primary() let mut expr = self.parse_primary()?;
while self.expect(&[TokenType::LeftParen]).is_some() {
expr = self.parse_call_arguments(expr)?;
}
Ok(expr)
} }
} }
@ -543,27 +547,23 @@ impl Parser {
TokenType::Number(_) | &TokenType::String(_) => Ok(ast::ExprNode::Litteral { TokenType::Number(_) | &TokenType::String(_) => Ok(ast::ExprNode::Litteral {
value: self.advance().clone(), value: self.advance().clone(),
}), }),
TokenType::Identifier(_) => { TokenType::Identifier(_) => Ok(ast::ExprNode::Variable {
let identifier = self.advance().clone(); name: self.advance().clone(),
if self.expect(&[TokenType::LeftParen]).is_some() { }),
self.parse_call(identifier)
} else {
Ok(ast::ExprNode::Variable { name: identifier })
}
}
_ => Err(ParserError::new(self.peek(), "expected expression")), _ => Err(ParserError::new(self.peek(), "expected expression")),
} }
} }
} }
/// Parse the following rules: /// Help parsing the following rules:
/// ``` /// ```
/// call := IDENTIFIER "(" arguments? ")" /// call := expression "(" arguments? ")"
/// arguments := expression ( "," expression )* /// arguments := expression ( "," expression )*
/// ``` /// ```
/// The `identifier` has already been read and is provided to the method; fn parse_call_arguments(
/// the opening parenthesis has already been skipped. &mut self,
fn parse_call(&mut self, name: Token) -> Result<ast::ExprNode, ParserError> { callee: ast::ExprNode,
) -> Result<ast::ExprNode, ParserError> {
let mut arguments = Vec::new(); let mut arguments = Vec::new();
if !self.check(&TokenType::RightParen) { if !self.check(&TokenType::RightParen) {
loop { loop {
@ -583,7 +583,7 @@ impl Parser {
.consume(&TokenType::RightParen, "')' expected after arguments")? .consume(&TokenType::RightParen, "')' expected after arguments")?
.clone(); .clone();
Ok(ast::ExprNode::Call { Ok(ast::ExprNode::Call {
name, callee: Box::new(callee),
right_paren, right_paren,
arguments, arguments,
}) })