added statements, but this isn't working

main
annieversary 2021-09-26 18:49:46 +02:00
parent 7ed7c03352
commit 48cb1f7278
3 changed files with 178 additions and 19 deletions

View File

@ -24,9 +24,10 @@ pub enum BinOp {
GreaterThan,
}
#[derive(Debug, PartialEq, Clone)]
pub enum Stmt {
Expr(Expr),
Var(Identifier, Expr),
Let(Identifier, Expr),
Assign(Identifier, Expr),
If(Expr, Vec<Stmt>),
While(Expr, Vec<Stmt>),

View File

@ -2,10 +2,12 @@ mod ast;
mod parser;
fn main() {
let a = r#"1 + a < 9 - <- chan"#;
let (rest, res) = parser::expr(a).unwrap();
let a = r#"
if (n < 2) {
return n;
}
"#;
let (rest, res) = parser::stmt(a).unwrap();
dbg!(res);
dbg!(rest);
println!("Hello, world!");
}

View File

@ -2,7 +2,7 @@ use nom::{
branch::alt,
bytes::complete::{escaped, is_not, tag, take_until},
character::complete::{alpha1, alphanumeric1, char, multispace0, one_of, space0},
combinator::{cut, map, recognize, value},
combinator::{cut, map, opt, recognize, value},
error::ParseError,
multi::{fold_many0, many0, separated_list0},
number::complete::double,
@ -18,7 +18,6 @@ where
{
alt((value((), multispace0), pinline_comment, peol_comment))(i)
}
fn pinline_comment<'a, E>(i: &'a str) -> IResult<&'a str, (), E>
where
E: ParseError<&'a str>,
@ -30,32 +29,33 @@ fn peol_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (),
value((), pair(char('/'), is_not("\n\r")))(i)
}
fn semi(i: &str) -> IResult<&str, &str> {
preceded(sc, tag(";"))(i)
}
fn braces<'a, P, O, E>(a: P) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
where
P: Parser<&'a str, O, E>,
E: ParseError<&'a str>,
{
delimited(char('{'), a, char('}'))
map(tuple((tag("{"), sc, a, sc, tag("}"))), |(_, _, a, _, _)| a)
}
fn parens<'a, P, O, E>(a: P) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
where
P: Parser<&'a str, O, E>,
E: ParseError<&'a str>,
{
delimited(
tuple((tag("("), recognize(sc))),
a,
tuple((recognize(sc), tag(")"))),
)
map(tuple((tag("("), sc, a, sc, tag(")"))), |(_, _, a, _, _)| a)
}
fn identifier(i: &str) -> IResult<&str, &str> {
println!("identifier: {}", i);
recognize(pair(
alt((alpha1, tag("_"))),
many0(alt((alphanumeric1, tag("_")))),
))(i)
preceded(
sc,
recognize(pair(
alt((alpha1, tag("_"))),
many0(alt((alphanumeric1, tag("_")))),
)),
)(i)
}
fn variable(i: &str) -> IResult<&str, Expr> {
@ -193,6 +193,113 @@ pub fn expr<'a>(i: &'a str) -> IResult<&'a str, Expr> {
binary(i)
}
fn if_stmt(i: &str) -> IResult<&str, Stmt> {
println!("if: {}", i);
map(
tuple((tag("if"), sc, parens(expr), sc, braces(many0(stmt)))),
|(_, _, expr, _, stmts)| Stmt::If(expr, stmts),
)(i)
}
fn while_stmt(i: &str) -> IResult<&str, Stmt> {
println!("while: {}", i);
map(
tuple((tag("while"), sc, parens(expr), sc, braces(many0(stmt)))),
|(_, _, expr, _, stmts)| Stmt::While(expr, stmts),
)(i)
}
fn let_stmt(i: &str) -> IResult<&str, Stmt> {
println!("let: {}", i);
map(
tuple((
tag("let"),
sc,
identifier,
tuple((sc, tag("="), sc)),
expr,
semi,
)),
|(_, _, id, _, expr, _)| Stmt::Let(id.to_string(), expr),
)(i)
}
fn yield_stmt(i: &str) -> IResult<&str, Stmt> {
println!("yield: {}", i);
map(tuple((tag("yield"), semi)), |_| Stmt::Yield)(i)
}
fn spawn_stmt(i: &str) -> IResult<&str, Stmt> {
println!("spawn: {}", i);
map(tuple((tag("spawn"), sc, expr, semi)), |(_, _, expr, _)| {
Stmt::Spawn(expr)
})(i)
}
fn return_stmt(i: &str) -> IResult<&str, Stmt> {
println!("return: {}", i);
map(
tuple((tag("return"), sc, opt(expr), semi)),
|(_, _, expr, _)| Stmt::Return(expr),
)(i)
}
fn func_stmt(i: &str) -> IResult<&str, Stmt> {
println!("func: {}", i);
map(
tuple((
tag("fn"),
sc,
identifier,
sc,
alt((
value(vec![], tuple((char('('), sc, char(')')))),
delimited(
char('('),
separated_list0(
tuple((sc, tag(","), sc)),
map(identifier, |a| a.to_string()),
),
char(')'),
),
)),
sc,
braces(many0(stmt)),
)),
|(_, _, id, _, params, _, stmts)| Stmt::Func(id.to_string(), params, stmts),
)(i)
}
fn assign_stmt(i: &str) -> IResult<&str, Stmt> {
println!("assign: {}", i);
map(
tuple((identifier, tuple((sc, tag("="), sc)), expr, semi)),
|(id, _, expr, _)| Stmt::Assign(id.to_string(), expr),
)(i)
}
fn send_stmt(i: &str) -> IResult<&str, Stmt> {
println!("send: {}", i);
map(
tuple((expr, tuple((sc, tag("->"), sc)), identifier, semi)),
|(expr, _, id, _)| Stmt::Send(expr, id.to_string()),
)(i)
}
fn expr_stmt(i: &str) -> IResult<&str, Stmt> {
println!("expr: {}", i);
map(tuple((expr, semi)), |(expr, _)| Stmt::Expr(expr))(i)
}
pub fn stmt(i: &str) -> IResult<&str, Stmt> {
preceded(
sc,
alt((
if_stmt,
while_stmt,
let_stmt,
yield_stmt,
spawn_stmt,
return_stmt,
func_stmt,
assign_stmt,
send_stmt,
expr_stmt,
)),
)(i)
}
#[cfg(test)]
mod tests {
use super::*;
@ -396,4 +503,53 @@ mod tests {
);
assert_eq!(rest, "");
}
#[test]
fn can_parse_let_stmt() {
let a = r#"let a = 0;"#;
let (rest, res) = stmt(a).unwrap();
assert_eq!(res, Stmt::Let("a".to_string(), Expr::LNum(0.0)));
assert_eq!(rest, "");
}
#[test]
fn can_parse_if_stmt() {
let a = r#"
if (n < 2) {
return n;
}
"#;
let (rest, res) = stmt(a).unwrap();
assert_eq!(
res,
Stmt::If(
Expr::Binary(
BinOp::LessThan,
Box::new(Expr::Var("n".to_string())),
Box::new(Expr::LNum(2.0)),
),
vec![Stmt::Return(Some(Expr::Var("n".to_string())))]
)
);
assert_eq!(rest, "");
}
#[test]
fn can_parse_func() {
let a = r#"
fn fib(n) {
if (n < 2) {
return n;
}
return fib(n - 2)
+ fib(n - 1);
}
"#;
let (rest, res) = stmt(a).unwrap();
assert_eq!(res, Stmt::Let("a".to_string(), Expr::LNum(0.0)));
assert_eq!(rest, "");
}
}