mirror of
https://github.com/azur1s/bobbylisp.git
synced 2024-10-16 02:37:40 -05:00
Compare commits
3 commits
b455c661a0
...
20decd8677
Author | SHA1 | Date | |
---|---|---|---|
Natapat Samutpong | 20decd8677 | ||
Natapat Samutpong | a3376f2492 | ||
Natapat Samutpong | 826092c54b |
|
@ -1,5 +1,10 @@
|
||||||
let foo :: String = "foo";
|
func join :: (a, b) = {
|
||||||
let bar :: String = "bar";
|
let result :: String = from(a, b);
|
||||||
func join :: (a , b) = {
|
return result
|
||||||
let baz :: String = "yay";
|
};
|
||||||
|
|
||||||
|
func main :: () = {
|
||||||
|
let foo :: String = join("f", "oo");
|
||||||
|
print(foo);
|
||||||
|
return 0
|
||||||
};
|
};
|
|
@ -94,6 +94,7 @@ fn lex_reserved_identifier(input: &Bytes) -> IResult<&Bytes, Token> {
|
||||||
"else" => Token::Else,
|
"else" => Token::Else,
|
||||||
"let" => Token::Let,
|
"let" => Token::Let,
|
||||||
"func" => Token::Func,
|
"func" => Token::Func,
|
||||||
|
"return" => Token::Return,
|
||||||
"true" => Token::Bool(true),
|
"true" => Token::Bool(true),
|
||||||
"false" => Token::Bool(false),
|
"false" => Token::Bool(false),
|
||||||
_ => Token::Identifier(syntax.to_string()),
|
_ => Token::Identifier(syntax.to_string()),
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub enum Token {
|
||||||
LBrace, RBrace,
|
LBrace, RBrace,
|
||||||
Semicolon, Colon, Comma,
|
Semicolon, Colon, Comma,
|
||||||
|
|
||||||
If, Else, Let, Func,
|
If, Else, Let, Func, Return,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Token struct with position information.
|
/// Token struct with position information.
|
||||||
|
@ -102,6 +102,8 @@ pub type Program = Vec<Stmt>;
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Let(Ident, Ident, Expr),
|
Let(Ident, Ident, Expr),
|
||||||
Func(Ident, Vec<Ident>, Vec<Stmt>),
|
Func(Ident, Vec<Ident>, Vec<Stmt>),
|
||||||
|
Call(Ident, Vec<Expr>),
|
||||||
|
Return(Expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
use nom::{
|
use nom::{
|
||||||
|
branch::alt,
|
||||||
bytes::complete::take,
|
bytes::complete::take,
|
||||||
combinator::{verify, map},
|
combinator::{verify, map, opt},
|
||||||
Err,
|
Err,
|
||||||
IResult, sequence::{terminated, tuple, pair, preceded, delimited}, multi::many0, branch::alt, error::{Error, ErrorKind},
|
error::{Error, ErrorKind},
|
||||||
|
IResult,
|
||||||
|
multi::many0,
|
||||||
|
sequence::{terminated, tuple, pair, preceded, delimited},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::model::{Token, Tokens, Precedence, Infix, Program, Stmt, Expr, Ident, Literal};
|
use super::model::{Token, Tokens, Precedence, Infix, Program, Stmt, Expr, Ident, Literal};
|
||||||
|
@ -17,6 +21,8 @@ macro_rules! tag_token (
|
||||||
|
|
||||||
tag_token!(tag_let, Token::Let);
|
tag_token!(tag_let, Token::Let);
|
||||||
tag_token!(tag_func, Token::Func);
|
tag_token!(tag_func, Token::Func);
|
||||||
|
tag_token!(tag_return, Token::Return);
|
||||||
|
|
||||||
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_semicolon, Token::Semicolon);
|
tag_token!(tag_semicolon, Token::Semicolon);
|
||||||
|
@ -83,21 +89,6 @@ fn parse_ident_expr(input: Tokens) -> IResult<Tokens, Expr> {
|
||||||
map(parse_ident, Expr::Ident)(input)
|
map(parse_ident, Expr::Ident)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_let_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
|
||||||
map(
|
|
||||||
tuple((
|
|
||||||
tag_let,
|
|
||||||
parse_ident,
|
|
||||||
tag_typehint,
|
|
||||||
parse_ident,
|
|
||||||
tag_assign,
|
|
||||||
parse_expr_lowest,
|
|
||||||
tag_semicolon,
|
|
||||||
)),
|
|
||||||
|(_, ident, _, typehint, _, expr, _)| Stmt::Let(ident, typehint, expr),
|
|
||||||
)(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_params(input: Tokens) -> IResult<Tokens, Vec<Ident>> {
|
fn parse_params(input: Tokens) -> IResult<Tokens, Vec<Ident>> {
|
||||||
map(
|
map(
|
||||||
pair(parse_ident, many0(preceded(tag_comma, parse_ident))),
|
pair(parse_ident, many0(preceded(tag_comma, parse_ident))),
|
||||||
|
@ -107,6 +98,86 @@ fn parse_params(input: Tokens) -> IResult<Tokens, Vec<Ident>> {
|
||||||
|
|
||||||
fn empty_params(input: Tokens) -> IResult<Tokens, Vec<Ident>> { Ok((input, vec![])) }
|
fn empty_params(input: Tokens) -> IResult<Tokens, Vec<Ident>> { Ok((input, vec![])) }
|
||||||
|
|
||||||
|
fn parse_call_expr(input: Tokens, func_handle: Expr) -> IResult<Tokens, Expr> {
|
||||||
|
map(
|
||||||
|
delimited(
|
||||||
|
tag_lparen,
|
||||||
|
parse_exprs,
|
||||||
|
tag_rparen,
|
||||||
|
),
|
||||||
|
|e| Expr::Call { func: Box::new(func_handle.clone()), args: e },
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_expr(input: Tokens, precedence: Precedence, left: Expr) -> IResult<Tokens, Expr> {
|
||||||
|
let (i1, t1) = take(1usize)(input)?;
|
||||||
|
|
||||||
|
if t1.tokens.is_empty() { Ok((i1, left)) }
|
||||||
|
else {
|
||||||
|
let p = infix_operator(&t1.tokens[0]);
|
||||||
|
match p {
|
||||||
|
(Precedence::Call, _) if precedence < Precedence::Call => {
|
||||||
|
let (i2, left2) = parse_call_expr(input, left)?;
|
||||||
|
parse_expr(i2, precedence, left2)
|
||||||
|
},
|
||||||
|
(ref peek, _) if precedence < *peek => {
|
||||||
|
// let (i2, left2) = parse_infix_expr(input, left)?;
|
||||||
|
// parse_expr(i2, precedence, left2)
|
||||||
|
todo!()
|
||||||
|
},
|
||||||
|
_ => Ok((input, left)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_comma_exprs(input: Tokens) -> IResult<Tokens, Expr> {
|
||||||
|
preceded(tag_comma, parse_expr_lowest)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_exprs(input: Tokens) -> IResult<Tokens, Vec<Expr>> {
|
||||||
|
map(
|
||||||
|
pair(parse_expr_lowest, many0(parse_comma_exprs)),
|
||||||
|
|(first, second)| [&vec![first][..], &second[..]].concat(),
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_expr_with(input: Tokens, precedence: Precedence) -> IResult<Tokens, Expr> {
|
||||||
|
let (i1, left) = parse_atom_expr(input)?;
|
||||||
|
parse_expr(i1, precedence, left)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_expr_lowest(input: Tokens) -> IResult<Tokens, Expr> {
|
||||||
|
parse_expr_with(input, Precedence::Lowest)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_return_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
||||||
|
map(
|
||||||
|
delimited(
|
||||||
|
tag_return,
|
||||||
|
parse_expr_lowest,
|
||||||
|
opt(tag_semicolon),
|
||||||
|
),
|
||||||
|
Stmt::Return,
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_call_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
||||||
|
map(
|
||||||
|
tuple((
|
||||||
|
parse_ident,
|
||||||
|
tag_lparen,
|
||||||
|
parse_exprs,
|
||||||
|
tag_rparen,
|
||||||
|
opt(tag_semicolon),
|
||||||
|
)),
|
||||||
|
|(ident, _, args, _, _)| Stmt::Call(ident, args),
|
||||||
|
)(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_block_stmt(input: Tokens) -> IResult<Tokens, Program> {
|
||||||
|
delimited(tag_lbrace, many0(parse_stmt), tag_rbrace)(input)
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_func_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
fn parse_func_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
||||||
map(
|
map(
|
||||||
tuple((
|
tuple((
|
||||||
|
@ -118,51 +189,33 @@ fn parse_func_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
||||||
tag_rparen,
|
tag_rparen,
|
||||||
tag_assign,
|
tag_assign,
|
||||||
parse_block_stmt,
|
parse_block_stmt,
|
||||||
tag_semicolon,
|
opt(tag_semicolon),
|
||||||
)),
|
)),
|
||||||
|(_, ident, _, _, params, _, _, block, _)| Stmt::Func(ident, params, block),
|
|(_, ident, _, _, params, _, _, block, _)| Stmt::Func(ident, params, block),
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr(input: Tokens, precedence: Precedence, left: Expr) -> IResult<Tokens, Expr> {
|
fn parse_let_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
||||||
let (i1, t1) = take(1usize)(input)?;
|
map(
|
||||||
|
tuple((
|
||||||
if t1.tokens.is_empty() { Ok((i1, left)) }
|
tag_let,
|
||||||
else {
|
parse_ident,
|
||||||
let p = infix_operator(&t1.tokens[0]);
|
tag_typehint,
|
||||||
match p {
|
parse_ident,
|
||||||
(Precedence::Call, _) if precedence < Precedence::Call => {
|
tag_assign,
|
||||||
// let (i2, left2) = parse_call_expr(input, left)?;
|
parse_expr_lowest,
|
||||||
// parse_expr(i2, precedence, left2)
|
opt(tag_semicolon),
|
||||||
todo!()
|
)),
|
||||||
},
|
|(_, ident, _, typehint, _, expr, _)| Stmt::Let(ident, typehint, expr),
|
||||||
(ref peek, _) if precedence < *peek => {
|
)(input)
|
||||||
// let (i2, left2) = parse_infix_expr(input, left)?;
|
|
||||||
// parse_expr(i2, precedence, left2)
|
|
||||||
todo!()
|
|
||||||
},
|
|
||||||
_ => Ok((input, left)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_expr_with(input: Tokens, precedence: Precedence) -> IResult<Tokens, Expr> {
|
|
||||||
let (i1, left) = parse_atom_expr(input)?;
|
|
||||||
parse_expr(i1, precedence, left)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_expr_lowest(input: Tokens) -> IResult<Tokens, Expr> {
|
|
||||||
parse_expr_with(input, Precedence::Lowest)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_block_stmt(input: Tokens) -> IResult<Tokens, Program> {
|
|
||||||
delimited(tag_lbrace, many0(parse_stmt), tag_rbrace)(input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
fn parse_stmt(input: Tokens) -> IResult<Tokens, Stmt> {
|
||||||
alt((
|
alt((
|
||||||
parse_let_stmt,
|
parse_let_stmt,
|
||||||
parse_func_stmt,
|
parse_func_stmt,
|
||||||
|
parse_call_stmt,
|
||||||
|
parse_return_stmt,
|
||||||
))(input)
|
))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ use clap::Parser as ArgParser;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
use args::{Args, Options};
|
use args::{Args, Options};
|
||||||
|
|
||||||
|
/// Front-end of the language.
|
||||||
|
/// Contains lexer, parser and token types.
|
||||||
pub mod front;
|
pub mod front;
|
||||||
use front::{lex::Lexer, parser::Parser, model::Tokens};
|
use front::{lex::Lexer, parser::Parser, model::Tokens};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue