From 4738ad92bf176324248e536fc012823443589e6c Mon Sep 17 00:00:00 2001 From: me Date: Tue, 16 Dec 2025 23:43:43 +0200 Subject: [PATCH] dot and return --- src/parser/parser.rs | 46 +++++++++++++++++-- .../ayin__parser__parser__tests__fn_def.snap | 10 ++-- ...__parser__parser__tests__paren_fncall.snap | 10 ++-- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 91dc3b0..09b9efc 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -14,6 +14,10 @@ pub fn parse(tokens: &mut Tokens, parser: Parser) -> Result { } } +pub fn parse_program(tokens: &mut Tokens) -> ParseResult { + Ok(parse_definitions(tokens)?.map(ast::Program)) +} + fn parse_definitions(tokens: &mut Tokens) -> ParseResult> { tokens.many(parse_definition) } @@ -40,6 +44,26 @@ fn parse_set(tokens: &mut Tokens) -> ParseResult { } } +fn parse_dot(tokens: &mut Tokens, expr: ast::Expr) -> Result { + if let Some(_dot) = tokens.next_if(&Token::Dot) { + if let Some(labels) = tokens.many_sep_by(&Token::Dot, parse_identifier_label)? { + Ok(labels + .into_iter() + .fold(expr, |acc, label| ast::Expr::Access { + expr: Box::new(acc), + field: label, + })) + } else { + Err(Error::UnexpectedToken { + expected: Token::Dot, + got: tokens.next(), + }) + } + } else { + Ok(expr) + } +} + fn parse_definition(tokens: &mut Tokens) -> ParseResult { if let Some(_) = tokens.next_if(&Token::Let) { if let Some(name) = parse_identifier_name(tokens)? { @@ -64,12 +88,13 @@ fn parse_definition(tokens: &mut Tokens) -> ParseResult { fn parse_expr(tokens: &mut Tokens) -> ParseResult { if let Some(expr1) = parse_simple_expr(tokens)? { + let expr1 = parse_dot(tokens, expr1)?; if let Some(args) = tokens.between(&Token::OpenParen, &Token::CloseParen, |ts| { ts.many_sep_by(&Token::Comma, parse_expr) })? { Ok(Some(ast::Expr::FunCall { func: Box::new(expr1), - args: args, + args, })) } else { Ok(parse_set(tokens)? @@ -131,7 +156,20 @@ fn parse_block(tokens: &mut Tokens) -> ParseResult> { fn parse_statement(tokens: &mut Tokens) -> ParseResult { tokens.one_of(vec![ - |tokens| Ok(parse_expr(tokens)?.map(ast::Statement::Expr)), + |tokens| { + if let Some(expr) = parse_expr(tokens)?.map(ast::Statement::Expr) { + if let Some(_) = tokens.next_if(&Token::Semicolon) { + Ok(Some(expr)) + } else { + Err(Error::UnexpectedToken { + expected: Token::Semicolon, + got: tokens.next(), + }) + } + } else { + Ok(None) + } + }, |tokens| Ok(parse_definition(tokens)?.map(ast::Statement::Let)), |tokens| { if let Some(_) = tokens.next_if(&Token::Return) { @@ -321,7 +359,7 @@ mod tests { } #[test] fn fn_def() { - let program = "fn(a1, boco, c_c) { 108 }".to_string(); + let program = "fn(a1, boco, c_c) { return 108; }".to_string(); let result = parse(&mut scan(program), parse_expr); insta::assert_debug_snapshot!(result); } @@ -333,7 +371,7 @@ mod tests { } #[test] fn paren_fncall() { - let program = "(fn(a1, boco, c_c) { 108 })()".to_string(); + let program = "(fn(a1, boco, c_c) { return 108; })()".to_string(); let result = parse(&mut scan(program), parse_expr); insta::assert_debug_snapshot!(result); } diff --git a/src/parser/snapshots/ayin__parser__parser__tests__fn_def.snap b/src/parser/snapshots/ayin__parser__parser__tests__fn_def.snap index 94a2c1c..ee43785 100644 --- a/src/parser/snapshots/ayin__parser__parser__tests__fn_def.snap +++ b/src/parser/snapshots/ayin__parser__parser__tests__fn_def.snap @@ -24,10 +24,12 @@ Ok( ], body: Block( [ - Expr( - Value( - Int( - 108, + Return( + Some( + Value( + Int( + 108, + ), ), ), ), diff --git a/src/parser/snapshots/ayin__parser__parser__tests__paren_fncall.snap b/src/parser/snapshots/ayin__parser__parser__tests__paren_fncall.snap index 3090d22..26bc391 100644 --- a/src/parser/snapshots/ayin__parser__parser__tests__paren_fncall.snap +++ b/src/parser/snapshots/ayin__parser__parser__tests__paren_fncall.snap @@ -25,10 +25,12 @@ Ok( ], body: Block( [ - Expr( - Value( - Int( - 108, + Return( + Some( + Value( + Int( + 108, + ), ), ), ),