parse calls

This commit is contained in:
nora 2021-11-02 23:01:20 +01:00
parent 7cba55578a
commit 031217f6c6
2 changed files with 52 additions and 4 deletions

View file

@ -93,6 +93,7 @@ pub enum Expr {
Literal(Literal), Literal(Literal),
UnaryOp(Box<UnaryOp>), UnaryOp(Box<UnaryOp>),
BinaryOp(Box<BinaryOp>), BinaryOp(Box<BinaryOp>),
Call(Box<Call>),
} }
impl Expr { impl Expr {
@ -102,6 +103,7 @@ impl Expr {
Expr::UnaryOp(unary) => unary.span, Expr::UnaryOp(unary) => unary.span,
Expr::BinaryOp(binary) => binary.span, Expr::BinaryOp(binary) => binary.span,
Expr::Ident(Ident { span, .. }) => *span, Expr::Ident(Ident { span, .. }) => *span,
Expr::Call(call) => call.span,
} }
} }
} }
@ -166,3 +168,16 @@ pub enum BinaryOpKind {
Div, Div,
Mod, Mod,
} }
#[derive(Debug, Clone, PartialEq)]
pub struct Call {
pub callee: Expr,
pub span: Span,
pub kind: CallKind,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CallKind {
Field(Ident),
Fn(Vec<Expr>),
}

View file

@ -286,7 +286,7 @@ impl<'code> Parser<'code> {
match self.peek_kind() { match self.peek_kind() {
Some(TokenType::Not) => { Some(TokenType::Not) => {
let unary_op_span = self.next().unwrap().span; let unary_op_span = self.next().unwrap().span;
let expr = self.unary()?; let expr = self.call()?;
Ok(Expr::UnaryOp(Box::new(UnaryOp { Ok(Expr::UnaryOp(Box::new(UnaryOp {
span: unary_op_span.extend(expr.span()), span: unary_op_span.extend(expr.span()),
expr, expr,
@ -295,18 +295,51 @@ impl<'code> Parser<'code> {
} }
Some(TokenType::Minus) => { Some(TokenType::Minus) => {
let unary_op_span = self.next().unwrap().span; let unary_op_span = self.next().unwrap().span;
let expr = self.unary()?; let expr = self.call()?;
Ok(Expr::UnaryOp(Box::new(UnaryOp { Ok(Expr::UnaryOp(Box::new(UnaryOp {
span: unary_op_span.extend(expr.span()), span: unary_op_span.extend(expr.span()),
expr, expr,
kind: UnaryOpKind::Neg, kind: UnaryOpKind::Neg,
}))) })))
} }
_ => self.primary(), _ => self.call(),
} }
} }
fn primary<'parser>(&'parser mut self) -> ParseResult<'code, Expr> { fn call(&mut self) -> ParseResult<'code, Expr> {
let mut expr = self.primary()?;
loop {
expr = match self.peek_kind() {
Some(TokenType::ParenO) => {
let open_span = self.expect(TokenType::ParenO)?.span;
let args = self.parse_list(TokenType::ParenC, Self::expression)?;
let close_span = self.expect(TokenType::ParenC)?.span;
Expr::Call(Box::new(Call {
callee: expr,
span: open_span.extend(close_span),
kind: CallKind::Fn(args),
}))
}
Some(TokenType::Dot) => {
let dot_span = self.expect(TokenType::Dot)?.span;
let field = self.ident()?;
Expr::Call(Box::new(Call {
callee: expr,
span: dot_span.extend(field.span),
kind: CallKind::Field(field),
}))
}
_ => break,
}
}
Ok(expr)
}
fn primary(&mut self) -> ParseResult<'code, Expr> {
let next = self.next().ok_or(ParseErr::Eof("primary"))?; let next = self.next().ok_or(ParseErr::Eof("primary"))?;
match next.kind { match next.kind {
TokenType::String(literal) => Ok(Expr::Literal(Literal::String(literal, next.span))), TokenType::String(literal) => Ok(Expr::Literal(Literal::String(literal, next.span))),