added statements, but this isn't working
parent
7ed7c03352
commit
48cb1f7278
|
@ -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>),
|
||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -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!");
|
||||
}
|
||||
|
|
178
src/parser.rs
178
src/parser.rs
|
@ -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);
|
||||
preceded(
|
||||
sc,
|
||||
recognize(pair(
|
||||
alt((alpha1, tag("_"))),
|
||||
many0(alt((alphanumeric1, tag("_")))),
|
||||
))(i)
|
||||
)),
|
||||
)(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, "");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue