added statements, but this isn't working
parent
7ed7c03352
commit
48cb1f7278
|
@ -24,9 +24,10 @@ pub enum BinOp {
|
||||||
GreaterThan,
|
GreaterThan,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Expr(Expr),
|
Expr(Expr),
|
||||||
Var(Identifier, Expr),
|
Let(Identifier, Expr),
|
||||||
Assign(Identifier, Expr),
|
Assign(Identifier, Expr),
|
||||||
If(Expr, Vec<Stmt>),
|
If(Expr, Vec<Stmt>),
|
||||||
While(Expr, Vec<Stmt>),
|
While(Expr, Vec<Stmt>),
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -2,10 +2,12 @@ mod ast;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let a = r#"1 + a < 9 - <- chan"#;
|
let a = r#"
|
||||||
let (rest, res) = parser::expr(a).unwrap();
|
if (n < 2) {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let (rest, res) = parser::stmt(a).unwrap();
|
||||||
dbg!(res);
|
dbg!(res);
|
||||||
dbg!(rest);
|
dbg!(rest);
|
||||||
|
|
||||||
println!("Hello, world!");
|
|
||||||
}
|
}
|
||||||
|
|
184
src/parser.rs
184
src/parser.rs
|
@ -2,7 +2,7 @@ use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{escaped, is_not, tag, take_until},
|
bytes::complete::{escaped, is_not, tag, take_until},
|
||||||
character::complete::{alpha1, alphanumeric1, char, multispace0, one_of, space0},
|
character::complete::{alpha1, alphanumeric1, char, multispace0, one_of, space0},
|
||||||
combinator::{cut, map, recognize, value},
|
combinator::{cut, map, opt, recognize, value},
|
||||||
error::ParseError,
|
error::ParseError,
|
||||||
multi::{fold_many0, many0, separated_list0},
|
multi::{fold_many0, many0, separated_list0},
|
||||||
number::complete::double,
|
number::complete::double,
|
||||||
|
@ -18,7 +18,6 @@ where
|
||||||
{
|
{
|
||||||
alt((value((), multispace0), pinline_comment, peol_comment))(i)
|
alt((value((), multispace0), pinline_comment, peol_comment))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pinline_comment<'a, E>(i: &'a str) -> IResult<&'a str, (), E>
|
fn pinline_comment<'a, E>(i: &'a str) -> IResult<&'a str, (), E>
|
||||||
where
|
where
|
||||||
E: ParseError<&'a str>,
|
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)
|
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>
|
fn braces<'a, P, O, E>(a: P) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
|
||||||
where
|
where
|
||||||
P: Parser<&'a str, O, E>,
|
P: Parser<&'a str, O, E>,
|
||||||
E: ParseError<&'a str>,
|
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>
|
fn parens<'a, P, O, E>(a: P) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
|
||||||
where
|
where
|
||||||
P: Parser<&'a str, O, E>,
|
P: Parser<&'a str, O, E>,
|
||||||
E: ParseError<&'a str>,
|
E: ParseError<&'a str>,
|
||||||
{
|
{
|
||||||
delimited(
|
map(tuple((tag("("), sc, a, sc, tag(")"))), |(_, _, a, _, _)| a)
|
||||||
tuple((tag("("), recognize(sc))),
|
|
||||||
a,
|
|
||||||
tuple((recognize(sc), tag(")"))),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn identifier(i: &str) -> IResult<&str, &str> {
|
fn identifier(i: &str) -> IResult<&str, &str> {
|
||||||
println!("identifier: {}", i);
|
println!("identifier: {}", i);
|
||||||
recognize(pair(
|
preceded(
|
||||||
alt((alpha1, tag("_"))),
|
sc,
|
||||||
many0(alt((alphanumeric1, tag("_")))),
|
recognize(pair(
|
||||||
))(i)
|
alt((alpha1, tag("_"))),
|
||||||
|
many0(alt((alphanumeric1, tag("_")))),
|
||||||
|
)),
|
||||||
|
)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn variable(i: &str) -> IResult<&str, Expr> {
|
fn variable(i: &str) -> IResult<&str, Expr> {
|
||||||
|
@ -193,6 +193,113 @@ pub fn expr<'a>(i: &'a str) -> IResult<&'a str, Expr> {
|
||||||
binary(i)
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -396,4 +503,53 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(rest, "");
|
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