add assignments

This commit is contained in:
nora 2021-11-03 21:04:11 +01:00
parent 63c9d5300c
commit 0b79d4500d
3 changed files with 78 additions and 8 deletions

View file

@ -13,13 +13,13 @@
| <break-stmt> | <break-stmt>
| <return-stmt> | <return-stmt>
| <block> | <block>
| <expression-statement>
<declaration> ::= "let" <IDENT> "=" <expression> ";" <declaration> ::= "let" <IDENT> "=" <expression> ";"
<assignment> ::= { call "." } <IDENT> "=" <expression> ";" <assignment> ::= { call "." } <IDENT> "=" <expression> ";"
| <expression> ";"
<fn-decl> ::= "fn" <IDENT> <fn-args> <block> <fn-decl> ::= "fn" <IDENT> <fn-args> <block>

View file

@ -75,9 +75,8 @@ impl<'code> Parser<'code> {
TokenType::Return => self.return_stmt(), TokenType::Return => self.return_stmt(),
TokenType::BraceO => Ok(Stmt::Block(self.block()?)), TokenType::BraceO => Ok(Stmt::Block(self.block()?)),
_ => { _ => {
let expr = self.expression()?; let stmt = self.assignment()?;
self.expect(TokenType::Semi)?; Ok(stmt)
Ok(Stmt::Expr(expr))
} }
} }
} }
@ -95,10 +94,6 @@ impl<'code> Parser<'code> {
})) }))
} }
fn assignment(&mut self) -> ParseResult<'code, Stmt> {
todo!("oh god no")
}
fn fn_decl(&mut self) -> ParseResult<'code, Stmt> { fn fn_decl(&mut self) -> ParseResult<'code, Stmt> {
let keyword_span = self.expect(TokenType::Fn)?.span; let keyword_span = self.expect(TokenType::Fn)?.span;
let name = self.ident()?; let name = self.ident()?;
@ -215,6 +210,24 @@ impl<'code> Parser<'code> {
} }
} }
fn assignment(&mut self) -> ParseResult<'code, Stmt> {
let expr = self.expression()?;
if let Some(TokenType::Equal) = self.peek_kind() {
let _ = self.expect(TokenType::Equal)?;
let init = self.expression()?;
let semi_span = self.expect(TokenType::Semi)?.span;
Ok(Stmt::Assignment(Assignment {
span: expr.span().extend(semi_span),
lhs: expr,
rhs: init,
}))
} else {
let _ = self.expect(TokenType::Semi)?;
Ok(Stmt::Expr(expr))
}
}
fn expression(&mut self) -> ParseResult<'code, Expr> { fn expression(&mut self) -> ParseResult<'code, Expr> {
self.logical_or() self.logical_or()
} }

View file

@ -73,6 +73,63 @@ fn test_number_literal<F: FnOnce(Vec<Token<'_>>) -> Expr>(parser: F) {
assert_eq!(num_lit(10.0), unary); assert_eq!(num_lit(10.0), unary);
} }
mod assignment {
use super::prelude::*;
fn parse_assignment(tokens: Vec<Token>) -> Stmt {
let mut parser = parser(tokens);
parser.assignment().unwrap()
}
#[test]
fn simple() {
let tokens = [Ident("hugo"), Equal, Number(10.0), Semi].map(token).into();
let ast = parse_assignment(tokens);
assert_eq!(
Stmt::Assignment(Assignment {
span: Default::default(),
lhs: Expr::Ident(ident("hugo")),
rhs: num_lit(10.0)
}),
ast
);
}
#[test]
fn call_expr() {
let tokens = [
Ident("hugo"),
Dot,
Ident("age"),
Equal,
Number(2021.0),
Minus,
Number(1986.0),
Semi,
]
.map(token)
.into();
let ast = parse_assignment(tokens);
assert_eq!(
Stmt::Assignment(Assignment {
span: Default::default(),
lhs: Expr::Call(Box::new(Call {
callee: Expr::Ident(ident("hugo")),
span: Default::default(),
kind: CallKind::Field(ident("age"))
})),
rhs: Expr::BinaryOp(Box::new(BinaryOp {
span: Default::default(),
lhs: num_lit(2021.0),
rhs: num_lit(1986.0),
kind: BinaryOpKind::Sub
}))
}),
ast
);
}
}
mod r#fn { mod r#fn {
use super::prelude::*; use super::prelude::*;