1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00

Compare commits

..

2 commits

Author SHA1 Message Date
Natapat Samutpong 0b82cf058f return type hint 2022-02-12 20:37:28 +07:00
Natapat Samutpong b4d3399a32 prefix and paren covered expr 2022-02-12 20:33:33 +07:00
4 changed files with 51 additions and 19 deletions

View file

@ -1,13 +1,15 @@
// user defined function // user defined function
func foo :: (a, b) = { func foo :: (a, b) -> Bool = {
return a; return a == b;
}; };
// entry point // entry point
func main :: () = { func main :: () -> Int = {
// if else in variable definition // if else in variable definition
let cond_str :: String = if true { return "t" } else { return "f" }; let cond_str :: String = if true { return "t" } else { return "f" };
// Infix operator // Infix operator
let n :: Bool = 2 == 2; let n :: Bool = 2 == 2;
// Prefix operator
let m :: Bool = !n;
}; };

View file

@ -31,18 +31,24 @@ syntax! { divide_operator , "/", Token::Div }
syntax! { not_operator , "!", Token::Not } syntax! { not_operator , "!", Token::Not }
// Punctuations // Punctuations
syntax! { typehint_punctuation , "::", Token::Typehint } syntax! { typehint_punctuation , "::", Token::Typehint }
syntax! { lparen_punctuation , "(", Token::LParen } syntax! { returnhint_punctuation , "->", Token::Return }
syntax! { rparen_punctuation , ")", Token::RParen } syntax! { lparen_punctuation , "(", Token::LParen }
syntax! { lbrace_punctuation , "{", Token::LBrace } syntax! { rparen_punctuation , ")", Token::RParen }
syntax! { rbrace_punctuation , "}", Token::RBrace } syntax! { lbrace_punctuation , "{", Token::LBrace }
syntax! { semicolon_punctuation , ";", Token::Semicolon } syntax! { rbrace_punctuation , "}", Token::RBrace }
syntax! { colon_punctuation , ":", Token::Colon } syntax! { semicolon_punctuation , ";", Token::Semicolon }
syntax! { comma_punctuation , ",", Token::Comma } syntax! { colon_punctuation , ":", Token::Colon }
syntax! { comma_punctuation , ",", Token::Comma }
// Operator & Punctuation // Operator & Punctuation
fn lex_operator_punctuation(input: &Bytes) -> IResult<&Bytes, Token> { fn lex_operator_punctuation(input: &Bytes) -> IResult<&Bytes, Token> {
alt(( alt((
typehint_punctuation, returnhint_punctuation,
lparen_punctuation, rparen_punctuation,
lbrace_punctuation, rbrace_punctuation,
semicolon_punctuation, colon_punctuation, comma_punctuation,
equal_operator, not_equal_operator, equal_operator, not_equal_operator,
less_than_operator, greater_than_operator, less_than_operator, greater_than_operator,
less_than_equal_operator, greater_than_equal_operator, less_than_equal_operator, greater_than_equal_operator,
@ -51,10 +57,6 @@ fn lex_operator_punctuation(input: &Bytes) -> IResult<&Bytes, Token> {
add_operator, subtract_operator, multiply_operator, divide_operator, add_operator, subtract_operator, multiply_operator, divide_operator,
not_operator, not_operator,
typehint_punctuation,
lparen_punctuation, rparen_punctuation,
lbrace_punctuation, rbrace_punctuation,
semicolon_punctuation, colon_punctuation, comma_punctuation,
))(input) ))(input)
} }

View file

@ -9,7 +9,7 @@ pub enum Token {
Identifier(String), String(String), Identifier(String), String(String),
Int(i64), Bool(bool), Int(i64), Bool(bool),
Assign, Typehint, Assign, Typehint, Returnhint,
Plus, Minus, Mul, Div, Not, Plus, Minus, Mul, Div, Not,
Eq, NEq, Lt, Gt, Lte, Gte, Eq, NEq, Lt, Gt, Lte, Gte,
@ -101,7 +101,7 @@ pub type Program = Vec<Stmt>;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum Stmt { pub enum Stmt {
Let(Ident, Ident, Expr), Let(Ident, Ident, Expr),
Func(Ident, Vec<Ident>, Vec<Stmt>), Func(Ident, Vec<Ident>, Ident, Vec<Stmt>),
Call(Ident, Vec<Expr>), Call(Ident, Vec<Expr>),
Return(Expr), Return(Expr),
} }
@ -138,6 +138,7 @@ pub struct Ident(pub String);
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum Prefix { pub enum Prefix {
Plus, Minus,
Not, Not,
} }

View file

@ -9,7 +9,7 @@ use nom::{
sequence::{terminated, tuple, pair, preceded, delimited}, error_position, sequence::{terminated, tuple, pair, preceded, delimited}, error_position,
}; };
use super::model::{Token, Tokens, Precedence, Infix, Program, Stmt, Expr, Ident, Literal}; use super::model::{Token, Tokens, Precedence, Infix, Program, Stmt, Expr, Ident, Literal, Prefix};
macro_rules! tag_token ( macro_rules! tag_token (
($func_name:ident, $tag: expr) => ( ($func_name:ident, $tag: expr) => (
@ -25,8 +25,13 @@ tag_token!(tag_return, Token::Return);
tag_token!(tag_if, Token::If); tag_token!(tag_if, Token::If);
tag_token!(tag_else, Token::Else); tag_token!(tag_else, Token::Else);
tag_token!(tag_plus, Token::Plus);
tag_token!(tag_minus, Token::Minus);
tag_token!(tag_not, Token::Not);
tag_token!(tag_assign, Token::Assign); tag_token!(tag_assign, Token::Assign);
tag_token!(tag_typehint, Token::Typehint); tag_token!(tag_typehint, Token::Typehint);
tag_token!(tag_returnhint, Token::Return);
tag_token!(tag_semicolon, Token::Semicolon); tag_token!(tag_semicolon, Token::Semicolon);
tag_token!(tag_lparen, Token::LParen); tag_token!(tag_lparen, Token::LParen);
tag_token!(tag_rparen, Token::RParen); tag_token!(tag_rparen, Token::RParen);
@ -73,10 +78,16 @@ fn parse_atom_expr(input: Tokens) -> IResult<Tokens, Expr> {
alt(( alt((
parse_literal_expr, parse_literal_expr,
parse_ident_expr, parse_ident_expr,
parse_prefix_expr,
parse_paren_expr,
parse_if_expr, parse_if_expr,
))(input) ))(input)
} }
fn parse_paren_expr(input: Tokens) -> IResult<Tokens, Expr> {
delimited(tag_lparen, parse_expr_lowest, tag_rparen)(input)
}
fn parse_ident(input: Tokens) -> IResult<Tokens, Ident> { fn parse_ident(input: Tokens) -> IResult<Tokens, Ident> {
let (i1, t1) = take(1usize)(input)?; let (i1, t1) = take(1usize)(input)?;
if t1.tokens.is_empty() { Err(Err::Error(Error::new(input, ErrorKind::Tag))) } if t1.tokens.is_empty() { Err(Err::Error(Error::new(input, ErrorKind::Tag))) }
@ -128,6 +139,20 @@ fn parse_infix_expr(input: Tokens, left: Expr) -> IResult<Tokens, Expr> {
} }
} }
fn parse_prefix_expr(input: Tokens) -> IResult<Tokens, Expr> {
let (i1, t1) = alt((tag_plus, tag_minus, tag_not))(input)?;
if t1.tokens.is_empty() { Err(Err::Error(error_position!(input, ErrorKind::Tag))) }
else {
let (i2, e) = parse_atom_expr(i1)?;
match t1.tokens[0].clone() {
Token::Plus => Ok((i2, Expr::Prefix(Prefix::Plus, Box::new(e)))),
Token::Minus => Ok((i2, Expr::Prefix(Prefix::Minus, Box::new(e)))),
Token::Not => Ok((i2, Expr::Prefix(Prefix::Not, Box::new(e)))),
_ => Err(Err::Error(error_position!(input, ErrorKind::Tag))),
}
}
}
fn parse_expr(input: Tokens, precedence: Precedence, left: Expr) -> IResult<Tokens, Expr> { fn parse_expr(input: Tokens, precedence: Precedence, left: Expr) -> IResult<Tokens, Expr> {
let (i1, t1) = take(1usize)(input)?; let (i1, t1) = take(1usize)(input)?;
@ -221,11 +246,13 @@ fn parse_func_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
tag_lparen, tag_lparen,
alt((parse_params, empty_params)), alt((parse_params, empty_params)),
tag_rparen, tag_rparen,
tag_returnhint,
parse_ident,
tag_assign, tag_assign,
parse_block_stmt, parse_block_stmt,
opt(tag_semicolon), opt(tag_semicolon),
)), )),
|(_, ident, _, _, params, _, _, block, _)| Stmt::Func(ident, params, block), |(_, ident, _, _, params, _, _, returntype, _, block, _)| Stmt::Func(ident, params, returntype, block),
)(input) )(input)
} }