From b455c661a0712ee4488300ca4a3390aa6ce6d7de Mon Sep 17 00:00:00 2001 From: Natapat Samutpong Date: Sat, 12 Feb 2022 15:04:44 +0700 Subject: [PATCH] feat: funcs ast --- example/hello_world.hyc | 7 +++++-- src/front/lex.rs | 6 +++++- src/front/model.rs | 4 +++- src/front/parser.rs | 43 ++++++++++++++++++++++++++++++++++++++--- src/main.rs | 11 +++++++++-- 5 files changed, 62 insertions(+), 9 deletions(-) diff --git a/example/hello_world.hyc b/example/hello_world.hyc index 98e246c..870e631 100644 --- a/example/hello_world.hyc +++ b/example/hello_world.hyc @@ -1,2 +1,5 @@ -let foo :: String = "Hello, "; -let bar :: String = "World!"; \ No newline at end of file +let foo :: String = "foo"; +let bar :: String = "bar"; +func join :: (a , b) = { + let baz :: String = "yay"; +}; \ No newline at end of file diff --git a/src/front/lex.rs b/src/front/lex.rs index f0b629b..ed459c7 100644 --- a/src/front/lex.rs +++ b/src/front/lex.rs @@ -34,8 +34,11 @@ syntax! { not_operator , "!", Token::Not } syntax! { typehint_punctuation , "::", Token::Typehint } syntax! { lparen_punctuation , "(", Token::LParen } syntax! { rparen_punctuation , ")", Token::RParen } +syntax! { lbrace_punctuation , "{", Token::LBrace } +syntax! { rbrace_punctuation , "}", Token::RBrace } syntax! { semicolon_punctuation , ";", Token::Semicolon } syntax! { colon_punctuation , ":", Token::Colon } +syntax! { comma_punctuation , ",", Token::Comma } // Operator & Punctuation fn lex_operator_punctuation(input: &Bytes) -> IResult<&Bytes, Token> { @@ -50,7 +53,8 @@ fn lex_operator_punctuation(input: &Bytes) -> IResult<&Bytes, Token> { typehint_punctuation, lparen_punctuation, rparen_punctuation, - semicolon_punctuation, colon_punctuation, + lbrace_punctuation, rbrace_punctuation, + semicolon_punctuation, colon_punctuation, comma_punctuation, ))(input) } diff --git a/src/front/model.rs b/src/front/model.rs index 3103c23..235efb6 100644 --- a/src/front/model.rs +++ b/src/front/model.rs @@ -14,7 +14,9 @@ pub enum Token { Plus, Minus, Mul, Div, Not, Eq, NEq, Lt, Gt, Lte, Gte, - LParen, RParen, Semicolon, Colon, + LParen, RParen, + LBrace, RBrace, + Semicolon, Colon, Comma, If, Else, Let, Func, } diff --git a/src/front/parser.rs b/src/front/parser.rs index 4fc1b72..c761a1d 100644 --- a/src/front/parser.rs +++ b/src/front/parser.rs @@ -2,7 +2,7 @@ use nom::{ bytes::complete::take, combinator::{verify, map}, Err, - IResult, sequence::{terminated, tuple}, multi::many0, branch::alt, error::{Error, ErrorKind}, + IResult, sequence::{terminated, tuple, pair, preceded, delimited}, multi::many0, branch::alt, error::{Error, ErrorKind}, }; use super::model::{Token, Tokens, Precedence, Infix, Program, Stmt, Expr, Ident, Literal}; @@ -16,9 +16,15 @@ macro_rules! tag_token ( ); tag_token!(tag_let, Token::Let); +tag_token!(tag_func, Token::Func); tag_token!(tag_assign, Token::Assign); tag_token!(tag_typehint, Token::Typehint); tag_token!(tag_semicolon, Token::Semicolon); +tag_token!(tag_lparen, Token::LParen); +tag_token!(tag_rparen, Token::RParen); +tag_token!(tag_lbrace, Token::LBrace); +tag_token!(tag_rbrace, Token::RBrace); +tag_token!(tag_comma, Token::Comma); tag_token!(tag_end_of_file, Token::EndOfFile); fn infix_operator(token: &Token) -> (Precedence, Option) { @@ -77,7 +83,7 @@ fn parse_ident_expr(input: Tokens) -> IResult { map(parse_ident, Expr::Ident)(input) } -fn parse_let(input: Tokens) -> IResult { +fn parse_let_stmt(input: Tokens) -> IResult { map( tuple(( tag_let, @@ -92,6 +98,32 @@ fn parse_let(input: Tokens) -> IResult { )(input) } +fn parse_params(input: Tokens) -> IResult> { + map( + pair(parse_ident, many0(preceded(tag_comma, parse_ident))), + |(p, ps)| [&vec![p][..], &ps[..]].concat(), + )(input) +} + +fn empty_params(input: Tokens) -> IResult> { Ok((input, vec![])) } + +fn parse_func_stmt(input: Tokens) -> IResult { + map( + tuple(( + tag_func, + parse_ident, + tag_typehint, + tag_lparen, + alt((parse_params, empty_params)), + tag_rparen, + tag_assign, + parse_block_stmt, + tag_semicolon, + )), + |(_, ident, _, _, params, _, _, block, _)| Stmt::Func(ident, params, block), + )(input) +} + fn parse_expr(input: Tokens, precedence: Precedence, left: Expr) -> IResult { let (i1, t1) = take(1usize)(input)?; @@ -123,9 +155,14 @@ fn parse_expr_lowest(input: Tokens) -> IResult { parse_expr_with(input, Precedence::Lowest) } +fn parse_block_stmt(input: Tokens) -> IResult { + delimited(tag_lbrace, many0(parse_stmt), tag_rbrace)(input) +} + fn parse_stmt(input: Tokens) -> IResult { alt(( - parse_let, + parse_let_stmt, + parse_func_stmt, ))(input) } diff --git a/src/main.rs b/src/main.rs index b88030b..895aaeb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,8 +16,15 @@ fn main() { let bytes: Vec = fs::read(src).unwrap(); let (_errs_, tokens) = Lexer::lex_tokens(&bytes).unwrap(); let tokens = Tokens::new(&tokens); - let (_errs_, ast) = Parser::parse(tokens).unwrap(); - println!("{:#?}", ast); + let ast = Parser::parse(tokens); + match ast { + Ok(ast) => { + println!("{:#?}", ast); + } + Err(err) => { + println!("{:#?}", err); + } + } }, } } \ No newline at end of file