use crate::{
ast::AST,
expr::{
ArgList, Content, Expr, Fn, FnCall, ModExpr, ParamList, Primitive, ReiType, TypeModifier,
UseExpr, VarDef,
},
lexer::Parser,
lexer::Token,
symtab::Identifier,
};
use log::info;
pub type ExprRes<T> = Result<T, Token>;
macro_rules! expr_none {
() => {
Err(Token::EOF)
};
}
fn var_def_expr(parser: &mut Parser) -> ExprRes<VarDef> {
let mut res = VarDef {
var_type_modifier: TypeModifier::Let,
lhs: Expr::Empty,
rhs: Expr::Empty,
};
let mut flag = false;
if parser.accept_ok(Token::Let) {
res.var_type_modifier = TypeModifier::Let;
flag = true;
} else if parser.accept_ok(Token::Const) {
res.var_type_modifier = TypeModifier::Const;
flag = true;
} else if parser.accept_ok(Token::Static) {
res.var_type_modifier = TypeModifier::Static;
flag = true;
} else if parser.accept_ok(Token::Mut) {
res.var_type_modifier = TypeModifier::Mut;
flag = true;
}
if flag {
res.lhs = expr(parser)?;
parser.expect(Token::Equals);
res.rhs = expr(parser)?;
return Ok(res);
}
expr_none!()
}
fn use_expr(parser: &mut Parser) -> ExprRes<UseExpr> {
match parser.accept(Token::Use) {
Ok(p) => {
info!("Found the use keyword");
let r = parser.expect(Token::Identifier);
let res = UseExpr {
namespace: r,
items: vec![],
};
if parser.accept(Token::DoubleColon).is_ok() {
parser.expect(Token::Star);
}
Ok(res)
}
Err(e) => expr_none!(),
}
}
pub const MAX_PARAMS: usize = 512;
fn param_list_expr(parser: &mut Parser) -> ExprRes<ParamList> {
let mut paramlist = ParamList { params: vec![] };
parser.accept(Token::ParenLeft)?;
for i in 0..MAX_PARAMS {
let name = parser.accept(Token::Identifier)?;
parser.expect(Token::Colon);
let param_type = parser.expect(Token::Identifier);
paramlist.params.push((name, param_type, None));
if !parser.accept_ok(Token::Comma) {
break;
}
}
parser.accept(Token::ParenRight)?;
return Ok(paramlist);
}
fn arg_list_expr(parser: &mut Parser) -> ExprRes<ArgList> {
let mut arglist = ArgList { args: vec![] };
parser.accept(Token::ParenLeft)?;
loop {
let res = parser.accept(Token::Identifier)?;
arglist.args.push(res);
if !parser.accept_ok(Token::Comma) {
break;
}
}
parser.accept(Token::ParenRight)?;
return Ok(arglist);
}
fn fn_call_expr(parser: &mut Parser) -> ExprRes<FnCall> {
let ident = parser.accept(Token::Identifier)?;
let arg_list = arg_list_expr(parser)?;
Ok(FnCall {
fn_name: ident,
args: arg_list,
})
}
fn fn_expr(parser: &mut Parser) -> ExprRes<Fn> {
if parser.accept_ok(Token::Function) {
info!("Found the fn keyword");
let name = parser.expect(Token::Identifier);
let paramlist = param_list_expr(parser)?;
if parser.accept_ok(Token::RightArrow) {}
let expr_body = expr(parser)?;
let res = Fn {
export: false,
fn_name: name,
fn_return_type: todo!(),
args: todo!(),
body: todo!(),
};
}
expr_none!()
}
fn mod_expr(parser: &mut Parser) -> ExprRes<Expr> {
if parser.accept_ok(Token::Module) {
info!("Found the mod keyword");
parser.expect(Token::Identifier);
parser.expect(Token::CurlyBraceLeft);
let res = expr(parser)?;
info!("Returning ok = {res:?}");
return Ok(ModExpr { body: res }.into());
}
expr_none!()
}
macro_rules! ret_expr {
($res:expr) => {
match $res {
Ok(ex) => return Ok(ex.into()),
Err(_) => (),
}
};
}
fn expr(parser: &mut Parser) -> ExprRes<Expr> {
ret_expr!(mod_expr(parser));
ret_expr!(use_expr(parser));
ret_expr!(fn_expr(parser));
ret_expr!(fn_call_expr(parser));
expr_none!()
}
fn content(parser: &mut Parser) -> Content {
let mut content = Content::default();
loop {
match expr(parser) {
Ok(r) => {
info!("Found an expression: {r:?}");
content.expressions.push(r);
}
Err(e) => break,
}
}
content
}
pub fn parse_tokens(mut parser: Parser) -> AST {
content(&mut parser)
}
#[test]
fn test_use_expr() {}