From 4f8ca415aa13c708593322e38f7fcddc22317fff Mon Sep 17 00:00:00 2001 From: LunarAkai Date: Sat, 9 Aug 2025 20:33:31 +0200 Subject: [PATCH] bool, functions, some more tests --- .../abstract_syntax_tree/ast.rs | 2 +- .../abstract_syntax_tree/definitions.rs | 14 +- .../abstract_syntax_tree/parser.rs | 145 +++++++++++++++--- 3 files changed, 131 insertions(+), 30 deletions(-) diff --git a/src/language_frontend/abstract_syntax_tree/ast.rs b/src/language_frontend/abstract_syntax_tree/ast.rs index 0ec3e5a..a8d4bfa 100644 --- a/src/language_frontend/abstract_syntax_tree/ast.rs +++ b/src/language_frontend/abstract_syntax_tree/ast.rs @@ -15,7 +15,7 @@ pub enum Expr { CharLiteral(char), - CalExpr(Call), + CallExpr(Call), UnaryExpr(Unary), diff --git a/src/language_frontend/abstract_syntax_tree/definitions.rs b/src/language_frontend/abstract_syntax_tree/definitions.rs index 3178139..1dc04d9 100644 --- a/src/language_frontend/abstract_syntax_tree/definitions.rs +++ b/src/language_frontend/abstract_syntax_tree/definitions.rs @@ -97,10 +97,10 @@ pub struct Condition { pub else_body: Option, } -/// Example: `x = 5` +/// Example: `x = y` #[derive(Clone, Debug, PartialEq)] pub struct Assignment { - pub target: Box, + pub target: String, pub value: Box, } @@ -119,7 +119,7 @@ pub struct Unary { pub operand: Box, } -/// Example: `x++` +/// Example: `1 + 1` #[derive(Clone, Debug, PartialEq)] pub struct Binary { pub lhs: Box, @@ -144,11 +144,11 @@ pub struct Binary { ///``` #[derive(Clone, Debug, PartialEq)] pub struct Function { - pub name: Rc, - pub params: Vec<(Ident, Type)>, + pub name: String, + pub params: Option>, pub return_type: Option, - pub body: Vec, - pub body_expr: Option, + pub body: Option>, + pub body_expr: Option>, } #[derive(Clone, Debug, PartialEq)] diff --git a/src/language_frontend/abstract_syntax_tree/parser.rs b/src/language_frontend/abstract_syntax_tree/parser.rs index e807a00..17a242a 100644 --- a/src/language_frontend/abstract_syntax_tree/parser.rs +++ b/src/language_frontend/abstract_syntax_tree/parser.rs @@ -1,7 +1,7 @@ use chumsky::{ Boxed, ConfigIterParser, IterParser, ParseResult, Parser, combinator::Or, - error::Rich, + error::{Rich, Simple}, extra, input::{Input, Stream, ValueInput}, prelude::{choice, end, just, nested_delimiters, recursive, skip_then_retry_until, via_parser}, @@ -43,27 +43,21 @@ fn parser<'src, I>() -> impl Parser<'src, I, Vec, extra::Err, { - let ident = select! { Token::Identifier(s) => s, }; - /* - let block = recursive(|block| { - let indent = just(Token::NewLine) - .ignore_then(just(Token::Indent)) - .ignore_then(block.clone().separated_by(just(Token::NewLine)).at_least(1)) - .then_ignore(just(Token::Dedent)); - - block.with_ctx(0) - }); - */ + let ident = select! { Token::Identifier(s) => s, }.labelled("identifier"); let expr = recursive(|expr| { let atom = select! { Token::FloatLiteral(x) => Expr::FloatLiteral(x), Token::IntLiteral(x) => Expr::IntLiteral(x), + Token::BoolLiteral(x) => Expr::BoolLiteral(x), + Token::StringLiteral(s) => Expr::StringLiteral(s), } + .labelled("value") .or(expr .clone() .delimited_by(just(Token::LParen), just(Token::RParen))); + // Product let mul_div = atom.clone().foldl( choice(( just(Token::Multiply).to(BinaryOp::Multiply), @@ -81,6 +75,7 @@ where }, ); + // Sum let add_sub = mul_div.clone().foldl( choice(( just(Token::Add).to(BinaryOp::Add), @@ -98,8 +93,19 @@ where }, ); - add_sub + let assign_expr = ident + .then_ignore(just(Token::Assign)) + .then(expr.clone()) + .map(|(name, value)| { + Expr::AssignmentExpr(Assignment { + target: name, + value: Box::new(value), + }) + }); + + assign_expr.or(add_sub) }); + let decl = recursive(|decl| { let var = just(Token::Var) .ignore_then(ident) @@ -113,19 +119,33 @@ where value: Box::new(rhs), }) }); - /* + let fun = just(Token::Fun) .ignore_then(ident.clone()) .then_ignore(just(Token::LParen)) + //.then(param_parser().separated_by(just(Token::Comma)).or_not().map(|p| p.unwrap_or_default())) .then_ignore(just(Token::RParen)) - .map(|(((name, args), ret), (body, body_expr))| Expr::Function(Function { - name, - params: args, - return_type: ret, - body, - body_expr - })); */ - var.or(expr) + .then( + just(Token::LBrace) + .then_ignore(just(Token::NewLine).or_not()) + .ignore_then(decl.clone().repeated()) + .then_ignore(just(Token::RBrace)) + .map(|stmts| (Some(stmts), None)) + .or(just(Token::Return) + .ignore_then(expr.clone()) + .map(|e| (None, Some(e)))), + ) + .then_ignore(just(Token::NewLine).or_not()) + .map(|(name, (body, body_expr))| { + Expr::FunctionExpr(Function { + name, + params: None, + return_type: None, + body: None, + body_expr: None, + }) + }); + var.or(fun).or(expr) }); decl.repeated().collect() @@ -148,6 +168,20 @@ mod tests { ) } + #[test] + fn test_bool() { + let var_bool = parse("var isUwU = true"); + assert!(var_bool.is_ok()); + assert_eq!( + var_bool.clone().unwrap(), + vec![Expr::VarExpr(Var { + ty: None, + ident: String::from("isUwU"), + value: Box::new(Expr::BoolLiteral(true)) + })] + ) + } + #[test] fn test_binary_expr() { let sum = parse("1 + 2"); @@ -175,4 +209,71 @@ mod tests { })] ) } + + #[test] + fn test_assignment() { + let assign = parse("x = 12"); + assert!(assign.is_ok()); + assert_eq!( + assign.clone().unwrap(), + vec![Expr::AssignmentExpr(Assignment { + target: String::from("x"), + value: Box::new(Expr::IntLiteral(12)) + })] + ) + } + + #[test] + fn test_function_decl() { + let empty_fun = parse("fun helloWorld() { }"); + assert!(empty_fun.is_ok()); + assert_eq!( + empty_fun.clone().unwrap(), + vec![Expr::FunctionExpr(Function { + name: String::from("helloWorld"), + params: None, + return_type: None, + body: None, + body_expr: None, + })] + ); + + let empty_fun_with_new_lines = parse( + r"fun emptyMulLines() { + + } + ", + ); + assert_eq!( + empty_fun_with_new_lines.clone().unwrap(), + vec![Expr::FunctionExpr(Function { + name: String::from("emptyMulLines"), + params: None, + return_type: None, + body: None, + body_expr: None, + })] + ); + + let fun_that_returns_int = parse( + r"fun returnsInt(): int { + -> 12 + } + ", + ); + assert_eq!( + empty_fun_with_new_lines.clone().unwrap(), + vec![Expr::FunctionExpr(Function { + name: String::from("returnsInt"), + params: None, + return_type: Some(Type::Integer), + body: None, + body_expr: Some(Box::new(Expr::IntLiteral(12))), + })] + ) + } } + +/* +var x = 10\nvar y = 5\n{\n var z = 7\n}\n10 + 10\n10 - 5\n5 * 5\n10 / 2 +*/