diff --git a/src/parse.rs b/src/parse.rs index ee3bb59..cee91b6 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -49,7 +49,7 @@ pub enum Definition<'a> { impl<'a> Definition<'a> { pub fn build_structure(lexer: &mut Lexer<'a>) -> Self { - let name = lexer.eat_id().unwrap(); + let name = lexer.eat_expect_id(); lexer.eat_expect(Token::BraceOpen); let mut members = Vec::new(); @@ -57,7 +57,7 @@ impl<'a> Definition<'a> { loop { match lexer.eat_id() { Ok(member_type) => { - let member_name = lexer.eat_id().unwrap(); + let member_name = lexer.eat_expect_id(); members.push(StructMember { type_name: member_type, name: member_name, @@ -81,7 +81,7 @@ impl<'a> Definition<'a> { loop { match lexer.eat_id() { Ok(member_type) => { - let member_name = lexer.eat_id().unwrap(); + let member_name = lexer.eat_expect_id(); args.push(FunctionArg { type_name: member_type, name: member_name, @@ -140,7 +140,7 @@ impl<'a> FunctionSignature<'a> { loop { match lexer.eat_id() { Ok(member_type) => { - let member_name = lexer.eat_id().unwrap(); + let member_name = lexer.eat_expect_id(); args.push(FunctionArg { type_name: member_type, name: member_name, @@ -176,25 +176,52 @@ pub struct FunctionBody<'a> { impl<'a> FunctionBody<'a> { pub fn build(lexer: &mut Lexer<'a>) -> Self { - let mut level = 1; - while level > 0 { - match lexer.next().unwrap() { - Token::BraceOpen => level += 1, - Token::BraceClose => level -= 1, - _ => {} + let mut statements = Vec::new(); + + let mut tail = Some(Token::Semicolon); + loop { + match tail { + Some(Token::Semicolon) => match lexer.next().unwrap() { + Token::Let => { + let (statement, next) = Statement::build_let(lexer); + statements.push(statement); + tail = Some(next); + } + Token::Var => { + let (statement, next) = Statement::build_var(lexer); + statements.push(statement); + tail = Some(next); + } + Token::Identifier => { + let var = lexer.slice(); + let (expr, next) = Statement::eat_assign(lexer); + statements.push(Statement::Assign { var, expr }); + tail = Some(next); + } + Token::BraceClose => break, + _ => lexer.panic_message("Expected var, let, or assign"), + }, + Some(Token::BraceClose) => break, + _ => lexer.panic_message("Unexpected token"), } } Self { - statements: Vec::new(), + statements, tail_expression: None, } } } +type ExpressionPair<'a> = Box<(Expression<'a>, Expression<'a>)>; + #[derive(Debug)] pub enum Expression<'a> { - Arithmetic(&'a str), + BinaryOp(BinaryOp, ExpressionPair<'a>), + Literal(Literal<'a>), + Local(&'a str), + Member(&'a str), + FuncCall(&'a str, Vec>), If { test_expr: Box>, then_body: BranchBody<'a>, @@ -202,6 +229,78 @@ pub enum Expression<'a> { }, } +impl<'a> Expression<'a> { + pub fn build(lexer: &mut Lexer<'a>) -> (Option, Token) { + let tok = lexer.next().unwrap(); + let lhs = match tok { + Token::Identifier => Self::Local(lexer.slice()), + Token::Dot => Self::Member(lexer.eat_expect_id()), + Token::Semicolon | Token::BraceClose | Token::ParanClose => return (None, tok), + _ => lexer.panic_message("Unexpected token"), + }; + + let (rhs, next) = Self::eat_op(lexer); + if let Some((op, rhs)) = rhs { + (Some(Self::BinaryOp(op, Box::new((lhs, rhs)))), next) + } else { + (Some(lhs), next) + } + } + + fn eat_op(lexer: &mut Lexer<'a>) -> (Option<(BinaryOp, Self)>, Token) { + let tok = lexer.next().unwrap(); + if let Some(op) = BinaryOp::from_token(tok) { + match Self::build(lexer) { + (Some(rhs), tail) => (Some((op, rhs)), tail), + _ => lexer.panic_message("Expected right-hand expression"), + } + } else { + (None, tok) + } + } +} + +#[derive(Debug)] +pub enum BinaryOp { + Add, + Sub, + Mul, + Div, + Less, + LessEq, + Greater, + GreaterEq, + Eq, + Neq, +} + +impl BinaryOp { + pub fn from_token(tok: Token) -> Option { + use BinaryOp::*; + use Token::*; + match tok { + OpAdd => Some(Add), + OpSub => Some(Sub), + OpMul => Some(Mul), + OpDiv => Some(Div), + OpLess => Some(Less), + OpLessEq => Some(LessEq), + OpGreater => Some(Greater), + OpGreaterEq => Some(GreaterEq), + OpEq => Some(Eq), + OpNeq => Some(Neq), + _ => None, + } + } +} + +#[derive(Debug)] +pub enum Literal<'a> { + BinaryInteger(&'a str), + OctalInteger(&'a str), + DecimalInteger(&'a str), +} + #[derive(Debug)] pub enum Statement<'a> { Assign { @@ -223,6 +322,26 @@ pub enum Statement<'a> { }, } +impl<'a> Statement<'a> { + pub fn eat_assign(lexer: &mut Lexer<'a>) -> (Expression<'a>, Token) { + lexer.eat_expect(Token::OpAssign); + let (expr, tail) = Expression::build(lexer); + (expr.unwrap(), tail) + } + + pub fn build_let(lexer: &mut Lexer<'a>) -> (Self, Token) { + let var = lexer.eat_expect_id(); + let (expr, tail) = Self::eat_assign(lexer); + (Self::Let { var, expr }, tail) + } + + pub fn build_var(lexer: &mut Lexer<'a>) -> (Self, Token) { + let var = lexer.eat_expect_id(); + let (expr, tail) = Self::eat_assign(lexer); + (Self::Var { var, expr }, tail) + } +} + #[derive(Debug)] pub struct BranchBody<'a> { pub statements: Vec>, @@ -244,6 +363,11 @@ mod tests { parse(include_str!("test/function.fae")); } + #[test] + fn tail_expression() { + parse("fn add(i32 x, i32 y) i32 { x + y }"); + } + #[test] fn structure() { parse(include_str!("test/structure.fae")); @@ -253,4 +377,40 @@ mod tests { fn example() { parse(include_str!("test/example.fae")); } + + mod expr { + use super::*; + + fn parse_expr(source: &str) { + let mut lex = Lexer::new(source); + let expr = Expression::build(&mut lex); + println!("{:#?}", expr); + assert_eq!(expr.1, Token::Semicolon); + } + + #[test] + fn locals() { + parse_expr("local1 + local2 - local3;"); + } + + #[test] + fn members() { + parse_expr(".member1 * .member2;"); + } + + #[test] + fn func_call() { + parse_expr("func_call();"); + } + + #[test] + fn method() { + parse_expr(".method();"); + } + + #[test] + fn submembers() { + parse_expr(".member.submember1 / .member.submember2.submember3;"); + } + } } diff --git a/src/test/function.fae b/src/test/function.fae index 8abd778..5b939e1 100644 --- a/src/test/function.fae +++ b/src/test/function.fae @@ -1,4 +1,6 @@ -fn free_floating(i32 arg1, i32 arg2) ReturnType {} +fn free_floating(i32 arg1, i32 arg2) ReturnType { + let local_var = arg1 + arg2; +} // associated function for the World struct World fn set_next(i32 i, i32 j) {