This commit is contained in:
LunarAkai 2025-11-19 23:37:47 +01:00
commit 79975ffcba
4 changed files with 102 additions and 30 deletions

View file

@ -148,7 +148,7 @@ pub struct Function {
pub params: Option<Vec<(String, Type)>>,
pub return_type: Option<Type>,
pub body: Option<BlockExpression>,
pub body_expr: Option<Box<Expr>>, // ' -> (return)'
pub return_expr: Box<Option<Expr>>, // ' -> (return)'
}
#[derive(Clone, Debug, PartialEq)]

View file

@ -1,3 +1,52 @@
pub mod ast;
pub mod definitions;
pub mod parser;
#[macro_export]
macro_rules! token {
(var) => {
just(Token::Var)
};
(=) => {
just(Token::Assign)
};
(if) => {
just(Token::If)
};
(else) => {
just(Token::Else)
};
(->) => {
just(Token::Return)
};
(:) => {
just(Token::Colon)
};
(,) => {
just(Token::Comma)
};
(*) => {
just(Token::Multiply)
};
(/) => {
just(Token::Divide)
};
(+) => {
just(Token::Add)
};
(-) => {
just(Token::Substract)
};
(lp) => {
just(Token::LParen)
};
(rp) => {
just(Token::RParen)
};
(lbrace) => {
just(Token::LBrace)
};
(rbrace) => {
just(Token::RBrace)
};
}

View file

@ -1,6 +1,7 @@
use chumsky::{
Boxed, ConfigIterParser, IterParser, ParseResult, Parser,
combinator::Or,
container::Seq,
error::{Rich, Simple},
extra,
input::{Input, Stream, ValueInput},
@ -14,11 +15,15 @@ use chumsky::{
newline, whitespace,
},
};
use inkwell::Either;
use logos::{Logos, source};
use crate::language_frontend::{
abstract_syntax_tree::{ast::Expr, definitions::*},
lexer::tokens::Token,
use crate::{
language_frontend::{
abstract_syntax_tree::{ast::Expr, definitions::*},
lexer::tokens::Token,
},
token,
};
// goal of parsing is to construct an abstract syntax tree
@ -50,15 +55,13 @@ where
Token::StringLiteral(s) => Expr::StringLiteral(s),
}
.labelled("value")
.or(expr
.clone()
.delimited_by(just(Token::LParen), just(Token::RParen)));
.or(expr.clone().delimited_by(token!(lp), token!(rp)));
// Product
let mul_div = atom.clone().foldl(
choice((
just(Token::Multiply).to(BinaryOp::Multiply),
just(Token::Divide).to(BinaryOp::Divide),
token!(*).to(BinaryOp::Multiply),
token!(/).to(BinaryOp::Divide),
))
.then(atom)
.then_ignore(just(Token::NewLine).or_not())
@ -75,8 +78,8 @@ where
// Sum
let add_sub = mul_div.clone().foldl(
choice((
just(Token::Add).to(BinaryOp::Add),
just(Token::Substract).to(BinaryOp::Substract),
token!(+).to(BinaryOp::Add),
token!(-).to(BinaryOp::Substract),
))
.then(mul_div)
.then_ignore(just(Token::NewLine).or_not())
@ -91,7 +94,7 @@ where
);
let assign_expr = ident
.then_ignore(just(Token::Assign))
.then_ignore(token!(=))
.then(expr.clone())
.map(|(name, value)| {
Expr::AssignmentExpr(Assignment {
@ -104,9 +107,9 @@ where
});
let decl = recursive(|decl| {
let var = just(Token::Var)
let var = token!(var)
.ignore_then(ident)
.then_ignore(just(Token::Assign))
.then_ignore(token!(=))
.then(expr.clone())
.then_ignore(just(Token::NewLine).or_not())
.map(|(name, rhs)| {
@ -124,11 +127,9 @@ where
just(Token::StringType).to(Type::String),
));
let return_type_parser = just(Token::Colon).ignore_then(type_parser.clone()).or_not();
let return_type_parser = token!(:).ignore_then(type_parser.clone()).or_not();
let return_expr = just(Token::Return)
.ignore_then(expr.clone())
.map(|expr| (expr));
let return_expr = token!(->).ignore_then(expr.clone()).map(|expr| expr);
//---------------------------------------------------------------------------------------
// Function Parser
@ -138,33 +139,33 @@ where
.then(
// arguments
ident
.then_ignore(just(Token::Colon))
.then_ignore(token!(:))
.then(type_parser.clone())
.separated_by(just(Token::Comma))
.separated_by(token!(,))
.allow_trailing()
.collect::<Vec<_>>()
.delimited_by(just(Token::LParen), just(Token::RParen))
.delimited_by(token!(lp), token!(rp))
.or_not(),
)
.then(return_type_parser.clone()) // return type
.then_ignore(just(Token::LBrace)) // {
.then_ignore(token!(lbrace)) // {
.then_ignore(just(Token::NewLine).repeated().or_not())
.then_ignore(return_expr.or_not())
.then(
expr.clone()
.then_ignore(just(Token::NewLine))
.repeated()
.collect::<Vec<_>>(),
.collect::<Vec<Expr>>()
.then(return_expr.or_not()),
)
.then_ignore(just(Token::NewLine).repeated().or_not())
.then_ignore(just(Token::RBrace)) // }
.map(|(((name, params), return_ty), stmts)| {
.then_ignore(token!(rbrace)) // }
.map(|(((name, params), return_ty), (stmts, return_value))| {
Expr::FunctionExpr(Function {
name: name,
params,
return_type: return_ty,
body: Some(stmts),
body_expr: None,
return_expr: Box::new(return_value),
})
});
@ -261,7 +262,7 @@ mod tests {
params: Some([].to_vec()),
return_type: None,
body: Some([].to_vec()),
body_expr: None,
return_expr: Box::new(None),
})]
);
@ -279,7 +280,7 @@ mod tests {
params: Some([].to_vec()),
return_type: None,
body: Some([].to_vec()),
body_expr: None,
return_expr: Box::new(None),
})]
);
@ -292,12 +293,32 @@ mod tests {
);
assert_eq!(
fun_that_returns_int.clone().unwrap(),
vec![Expr::FunctionExpr(Function {
name: String::from("returnsInt"),
params: Some([].to_vec()),
return_type: Some(Type::Integer),
body: Some([].to_vec()),
return_expr: Box::new(Some(Expr::IntLiteral(12))),
})]
);
// tests for return expr with previous statements in functions
let fun_multi_line_return = parse(
r"fun returnsInt(): int {
var x = 12
x = x + 1
-> x
}
",
);
assert_eq!(
fun_multi_line_return.clone().unwrap(),
vec![Expr::FunctionExpr(Function {
name: String::from("returnsInt"),
params: Some([].to_vec()),
return_type: Some(Type::Integer),
body: Some(vec![Expr::IntLiteral(12)]),
body_expr: Some(Box::new(Expr::ReturnExpr)),
return_expr: Box::new(Some(Expr::ReturnExpr)),
})]
)
}

View file

@ -34,4 +34,6 @@ impl<'ctx> CodeGen<'ctx> {
exec_engine,
}
}
fn compile_expr(&mut self, expr: &Expr) {}
}