From 63fb726e6ee59f858aae89c4c4451fc9fe194008 Mon Sep 17 00:00:00 2001 From: Natapat Samutpong Date: Thu, 17 Feb 2022 20:44:36 +0700 Subject: [PATCH] if do block --- README.md | 1 + example/ex.hyc | 16 +++++++--- src/front/parse.rs | 77 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 00b68b5..d131744 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Hycron Programming language +Note: The syntax can still be changed, if you have an idea, feel free to make an issues about it. # TODO - Compliation diff --git a/example/ex.hyc b/example/ex.hyc index 536d4a0..b6302eb 100644 --- a/example/ex.hyc +++ b/example/ex.hyc @@ -1,5 +1,11 @@ -fun foo a b = a == b; -fun bar a b = { a == b }; -let res = foo(34, 35); -let res = { foo(34, 35) }; -/* comment */ \ No newline at end of file +fun foo a b = a * b; +let bar = foo(3, 3); + +if bar == 9 then + do + print(bar); + print(":)"); + end +else + print(":("); +end; \ No newline at end of file diff --git a/src/front/parse.rs b/src/front/parse.rs index f7e4c24..19e756d 100644 --- a/src/front/parse.rs +++ b/src/front/parse.rs @@ -15,7 +15,10 @@ pub enum Token { Comma, // Keywords + Import, Let, Fun, + If, Then, Else, End, + Do, } pub type Span = std::ops::Range; @@ -69,8 +72,14 @@ pub fn lexer() -> impl Parser, Error = Simple> { "true" => Token::Boolean(true), "false" => Token::Boolean(false), + "import" => Token::Import, "let" => Token::Let, "fun" => Token::Fun, + "if" => Token::If, + "then" => Token::Then, + "else" => Token::Else, + "end" => Token::End, + "do" => Token::Do, _ => Token::Ident(s), }); @@ -102,6 +111,7 @@ pub enum Expr { Unary { op: String, expr: Box }, Binary { op: String, left: Box, right: Box }, + Call { name: Box, args: Vec }, Let { name: String, @@ -112,10 +122,15 @@ pub enum Expr { args: Vec, body: Vec, }, - Call { - name: Box, - args: Vec, + + If { + cond: Box, + then: Vec, + else_: Vec, }, + Do { body: Vec }, + + Import(String), } fn expr_parser() -> impl Parser> + Clone { @@ -216,49 +231,83 @@ fn expr_parser() -> impl Parser> + Clone { }).labelled("expression"); let declare = recursive(|decl| { - let decl_block = decl.clone() - .or(expr.clone()) - .repeated() - .delimited_by(just(Token::Delimiter('{')), just(Token::Delimiter('}'))); + let do_block = just(Token::Do) + .ignore_then( + expr.clone() + .then_ignore(just(Token::Semicolon)) + .repeated()) + .then_ignore(just(Token::End)); let declare_var = just(Token::Let) .ignore_then(ident) .then_ignore(just(Token::Assign)) .then( - decl_block.clone() + do_block.clone() .or(decl.clone().repeated().at_most(1)) ) - .then_ignore(just(Token::Semicolon)) .map(|(name, value)| Expr::Let { name, value, - }); + }).labelled("variable"); let declare_fun = just(Token::Fun) .ignore_then(ident) .then(ident.repeated()) .then_ignore(just(Token::Assign)) .then( - decl_block.clone() + do_block.clone() .or(decl.clone().repeated().at_most(1)) ) - .then_ignore(just(Token::Semicolon)) .map(|((name, args), body)| Expr::Fun { name, args, body, - }); + }).labelled("function"); + + let declare_import = just(Token::Import) + .ignore_then(ident.clone()) + .map(Expr::Import); + + let if_cond = just(Token::If) + .ignore_then(expr.clone()) + .then_ignore(just(Token::Then)) + .then( + do_block.clone() + .or(decl.clone() + .repeated() + .at_most(1) + .then_ignore(just(Token::Semicolon))) + ) + .then_ignore(just(Token::Else)) + .then( + do_block.clone() + .or(decl.clone() + .repeated() + .at_most(1) + .then_ignore(just(Token::Semicolon))) + ) + .then_ignore(just(Token::End)) + .map(|((cond, then), else_)| Expr::If { + cond: Box::new(cond), + then, + else_, + }).labelled("if"); declare_var .or(declare_fun) + .or(declare_import) + .or(if_cond) + .or(do_block.map(|body| Expr::Do { body })) .or(expr) - }); + + }).labelled("declare"); declare } pub fn parser() -> impl Parser, Error = Simple> + Clone { expr_parser() + .then_ignore(just(Token::Semicolon)) .repeated() .then_ignore(end()) } \ No newline at end of file