bool, functions, some more tests
This commit is contained in:
parent
50526960ba
commit
4f8ca415aa
3 changed files with 131 additions and 30 deletions
|
|
@ -15,7 +15,7 @@ pub enum Expr {
|
|||
|
||||
CharLiteral(char),
|
||||
|
||||
CalExpr(Call),
|
||||
CallExpr(Call),
|
||||
|
||||
UnaryExpr(Unary),
|
||||
|
||||
|
|
|
|||
|
|
@ -97,10 +97,10 @@ pub struct Condition {
|
|||
pub else_body: Option<BlockStatement>,
|
||||
}
|
||||
|
||||
/// Example: `x = 5`
|
||||
/// Example: `x = y`
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Assignment {
|
||||
pub target: Box<Expr>,
|
||||
pub target: String,
|
||||
pub value: Box<Expr>,
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +119,7 @@ pub struct Unary {
|
|||
pub operand: Box<Expr>,
|
||||
}
|
||||
|
||||
/// Example: `x++`
|
||||
/// Example: `1 + 1`
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Binary {
|
||||
pub lhs: Box<Expr>,
|
||||
|
|
@ -144,11 +144,11 @@ pub struct Binary {
|
|||
///```
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Function {
|
||||
pub name: Rc<str>,
|
||||
pub params: Vec<(Ident, Type)>,
|
||||
pub name: String,
|
||||
pub params: Option<Vec<(Ident, Type)>>,
|
||||
pub return_type: Option<Type>,
|
||||
pub body: Vec<Statement>,
|
||||
pub body_expr: Option<Type>,
|
||||
pub body: Option<Vec<Expr>>,
|
||||
pub body_expr: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use chumsky::{
|
||||
Boxed, ConfigIterParser, IterParser, ParseResult, Parser,
|
||||
combinator::Or,
|
||||
error::Rich,
|
||||
error::{Rich, Simple},
|
||||
extra,
|
||||
input::{Input, Stream, ValueInput},
|
||||
prelude::{choice, end, just, nested_delimiters, recursive, skip_then_retry_until, via_parser},
|
||||
|
|
@ -43,27 +43,21 @@ fn parser<'src, I>() -> impl Parser<'src, I, Vec<Expr>, extra::Err<Rich<'src, To
|
|||
where
|
||||
I: ValueInput<'src, Token = Token, Span = SimpleSpan>,
|
||||
{
|
||||
let ident = select! { Token::Identifier(s) => s, };
|
||||
/*
|
||||
let block = recursive(|block| {
|
||||
let indent = just(Token::NewLine)
|
||||
.ignore_then(just(Token::Indent))
|
||||
.ignore_then(block.clone().separated_by(just(Token::NewLine)).at_least(1))
|
||||
.then_ignore(just(Token::Dedent));
|
||||
|
||||
block.with_ctx(0)
|
||||
});
|
||||
*/
|
||||
let ident = select! { Token::Identifier(s) => s, }.labelled("identifier");
|
||||
|
||||
let expr = recursive(|expr| {
|
||||
let atom = select! {
|
||||
Token::FloatLiteral(x) => Expr::FloatLiteral(x),
|
||||
Token::IntLiteral(x) => Expr::IntLiteral(x),
|
||||
Token::BoolLiteral(x) => Expr::BoolLiteral(x),
|
||||
Token::StringLiteral(s) => Expr::StringLiteral(s),
|
||||
}
|
||||
.labelled("value")
|
||||
.or(expr
|
||||
.clone()
|
||||
.delimited_by(just(Token::LParen), just(Token::RParen)));
|
||||
|
||||
// Product
|
||||
let mul_div = atom.clone().foldl(
|
||||
choice((
|
||||
just(Token::Multiply).to(BinaryOp::Multiply),
|
||||
|
|
@ -81,6 +75,7 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
// Sum
|
||||
let add_sub = mul_div.clone().foldl(
|
||||
choice((
|
||||
just(Token::Add).to(BinaryOp::Add),
|
||||
|
|
@ -98,8 +93,19 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
add_sub
|
||||
let assign_expr = ident
|
||||
.then_ignore(just(Token::Assign))
|
||||
.then(expr.clone())
|
||||
.map(|(name, value)| {
|
||||
Expr::AssignmentExpr(Assignment {
|
||||
target: name,
|
||||
value: Box::new(value),
|
||||
})
|
||||
});
|
||||
|
||||
assign_expr.or(add_sub)
|
||||
});
|
||||
|
||||
let decl = recursive(|decl| {
|
||||
let var = just(Token::Var)
|
||||
.ignore_then(ident)
|
||||
|
|
@ -113,19 +119,33 @@ where
|
|||
value: Box::new(rhs),
|
||||
})
|
||||
});
|
||||
/*
|
||||
|
||||
let fun = just(Token::Fun)
|
||||
.ignore_then(ident.clone())
|
||||
.then_ignore(just(Token::LParen))
|
||||
//.then(param_parser().separated_by(just(Token::Comma)).or_not().map(|p| p.unwrap_or_default()))
|
||||
.then_ignore(just(Token::RParen))
|
||||
.map(|(((name, args), ret), (body, body_expr))| Expr::Function(Function {
|
||||
name,
|
||||
params: args,
|
||||
return_type: ret,
|
||||
body,
|
||||
body_expr
|
||||
})); */
|
||||
var.or(expr)
|
||||
.then(
|
||||
just(Token::LBrace)
|
||||
.then_ignore(just(Token::NewLine).or_not())
|
||||
.ignore_then(decl.clone().repeated())
|
||||
.then_ignore(just(Token::RBrace))
|
||||
.map(|stmts| (Some(stmts), None))
|
||||
.or(just(Token::Return)
|
||||
.ignore_then(expr.clone())
|
||||
.map(|e| (None, Some(e)))),
|
||||
)
|
||||
.then_ignore(just(Token::NewLine).or_not())
|
||||
.map(|(name, (body, body_expr))| {
|
||||
Expr::FunctionExpr(Function {
|
||||
name,
|
||||
params: None,
|
||||
return_type: None,
|
||||
body: None,
|
||||
body_expr: None,
|
||||
})
|
||||
});
|
||||
var.or(fun).or(expr)
|
||||
});
|
||||
|
||||
decl.repeated().collect()
|
||||
|
|
@ -148,6 +168,20 @@ mod tests {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool() {
|
||||
let var_bool = parse("var isUwU = true");
|
||||
assert!(var_bool.is_ok());
|
||||
assert_eq!(
|
||||
var_bool.clone().unwrap(),
|
||||
vec![Expr::VarExpr(Var {
|
||||
ty: None,
|
||||
ident: String::from("isUwU"),
|
||||
value: Box::new(Expr::BoolLiteral(true))
|
||||
})]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_binary_expr() {
|
||||
let sum = parse("1 + 2");
|
||||
|
|
@ -175,4 +209,71 @@ mod tests {
|
|||
})]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assignment() {
|
||||
let assign = parse("x = 12");
|
||||
assert!(assign.is_ok());
|
||||
assert_eq!(
|
||||
assign.clone().unwrap(),
|
||||
vec![Expr::AssignmentExpr(Assignment {
|
||||
target: String::from("x"),
|
||||
value: Box::new(Expr::IntLiteral(12))
|
||||
})]
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_function_decl() {
|
||||
let empty_fun = parse("fun helloWorld() { }");
|
||||
assert!(empty_fun.is_ok());
|
||||
assert_eq!(
|
||||
empty_fun.clone().unwrap(),
|
||||
vec![Expr::FunctionExpr(Function {
|
||||
name: String::from("helloWorld"),
|
||||
params: None,
|
||||
return_type: None,
|
||||
body: None,
|
||||
body_expr: None,
|
||||
})]
|
||||
);
|
||||
|
||||
let empty_fun_with_new_lines = parse(
|
||||
r"fun emptyMulLines() {
|
||||
|
||||
}
|
||||
",
|
||||
);
|
||||
assert_eq!(
|
||||
empty_fun_with_new_lines.clone().unwrap(),
|
||||
vec![Expr::FunctionExpr(Function {
|
||||
name: String::from("emptyMulLines"),
|
||||
params: None,
|
||||
return_type: None,
|
||||
body: None,
|
||||
body_expr: None,
|
||||
})]
|
||||
);
|
||||
|
||||
let fun_that_returns_int = parse(
|
||||
r"fun returnsInt(): int {
|
||||
-> 12
|
||||
}
|
||||
",
|
||||
);
|
||||
assert_eq!(
|
||||
empty_fun_with_new_lines.clone().unwrap(),
|
||||
vec![Expr::FunctionExpr(Function {
|
||||
name: String::from("returnsInt"),
|
||||
params: None,
|
||||
return_type: Some(Type::Integer),
|
||||
body: None,
|
||||
body_expr: Some(Box::new(Expr::IntLiteral(12))),
|
||||
})]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
var x = 10\nvar y = 5\n{\n var z = 7\n}\n10 + 10\n10 - 5\n5 * 5\n10 / 2
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue