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),
|
CharLiteral(char),
|
||||||
|
|
||||||
CalExpr(Call),
|
CallExpr(Call),
|
||||||
|
|
||||||
UnaryExpr(Unary),
|
UnaryExpr(Unary),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,10 +97,10 @@ pub struct Condition {
|
||||||
pub else_body: Option<BlockStatement>,
|
pub else_body: Option<BlockStatement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Example: `x = 5`
|
/// Example: `x = y`
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Assignment {
|
pub struct Assignment {
|
||||||
pub target: Box<Expr>,
|
pub target: String,
|
||||||
pub value: Box<Expr>,
|
pub value: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ pub struct Unary {
|
||||||
pub operand: Box<Expr>,
|
pub operand: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Example: `x++`
|
/// Example: `1 + 1`
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Binary {
|
pub struct Binary {
|
||||||
pub lhs: Box<Expr>,
|
pub lhs: Box<Expr>,
|
||||||
|
|
@ -144,11 +144,11 @@ pub struct Binary {
|
||||||
///```
|
///```
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: Rc<str>,
|
pub name: String,
|
||||||
pub params: Vec<(Ident, Type)>,
|
pub params: Option<Vec<(Ident, Type)>>,
|
||||||
pub return_type: Option<Type>,
|
pub return_type: Option<Type>,
|
||||||
pub body: Vec<Statement>,
|
pub body: Option<Vec<Expr>>,
|
||||||
pub body_expr: Option<Type>,
|
pub body_expr: Option<Box<Expr>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use chumsky::{
|
use chumsky::{
|
||||||
Boxed, ConfigIterParser, IterParser, ParseResult, Parser,
|
Boxed, ConfigIterParser, IterParser, ParseResult, Parser,
|
||||||
combinator::Or,
|
combinator::Or,
|
||||||
error::Rich,
|
error::{Rich, Simple},
|
||||||
extra,
|
extra,
|
||||||
input::{Input, Stream, ValueInput},
|
input::{Input, Stream, ValueInput},
|
||||||
prelude::{choice, end, just, nested_delimiters, recursive, skip_then_retry_until, via_parser},
|
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
|
where
|
||||||
I: ValueInput<'src, Token = Token, Span = SimpleSpan>,
|
I: ValueInput<'src, Token = Token, Span = SimpleSpan>,
|
||||||
{
|
{
|
||||||
let ident = select! { Token::Identifier(s) => s, };
|
let ident = select! { Token::Identifier(s) => s, }.labelled("identifier");
|
||||||
/*
|
|
||||||
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 expr = recursive(|expr| {
|
let expr = recursive(|expr| {
|
||||||
let atom = select! {
|
let atom = select! {
|
||||||
Token::FloatLiteral(x) => Expr::FloatLiteral(x),
|
Token::FloatLiteral(x) => Expr::FloatLiteral(x),
|
||||||
Token::IntLiteral(x) => Expr::IntLiteral(x),
|
Token::IntLiteral(x) => Expr::IntLiteral(x),
|
||||||
|
Token::BoolLiteral(x) => Expr::BoolLiteral(x),
|
||||||
|
Token::StringLiteral(s) => Expr::StringLiteral(s),
|
||||||
}
|
}
|
||||||
|
.labelled("value")
|
||||||
.or(expr
|
.or(expr
|
||||||
.clone()
|
.clone()
|
||||||
.delimited_by(just(Token::LParen), just(Token::RParen)));
|
.delimited_by(just(Token::LParen), just(Token::RParen)));
|
||||||
|
|
||||||
|
// Product
|
||||||
let mul_div = atom.clone().foldl(
|
let mul_div = atom.clone().foldl(
|
||||||
choice((
|
choice((
|
||||||
just(Token::Multiply).to(BinaryOp::Multiply),
|
just(Token::Multiply).to(BinaryOp::Multiply),
|
||||||
|
|
@ -81,6 +75,7 @@ where
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Sum
|
||||||
let add_sub = mul_div.clone().foldl(
|
let add_sub = mul_div.clone().foldl(
|
||||||
choice((
|
choice((
|
||||||
just(Token::Add).to(BinaryOp::Add),
|
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 decl = recursive(|decl| {
|
||||||
let var = just(Token::Var)
|
let var = just(Token::Var)
|
||||||
.ignore_then(ident)
|
.ignore_then(ident)
|
||||||
|
|
@ -113,19 +119,33 @@ where
|
||||||
value: Box::new(rhs),
|
value: Box::new(rhs),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
/*
|
|
||||||
let fun = just(Token::Fun)
|
let fun = just(Token::Fun)
|
||||||
.ignore_then(ident.clone())
|
.ignore_then(ident.clone())
|
||||||
.then_ignore(just(Token::LParen))
|
.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))
|
.then_ignore(just(Token::RParen))
|
||||||
.map(|(((name, args), ret), (body, body_expr))| Expr::Function(Function {
|
.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,
|
name,
|
||||||
params: args,
|
params: None,
|
||||||
return_type: ret,
|
return_type: None,
|
||||||
body,
|
body: None,
|
||||||
body_expr
|
body_expr: None,
|
||||||
})); */
|
})
|
||||||
var.or(expr)
|
});
|
||||||
|
var.or(fun).or(expr)
|
||||||
});
|
});
|
||||||
|
|
||||||
decl.repeated().collect()
|
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]
|
#[test]
|
||||||
fn test_binary_expr() {
|
fn test_binary_expr() {
|
||||||
let sum = parse("1 + 2");
|
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