Skip to content
This repository was archived by the owner on Apr 2, 2026. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 48 additions & 15 deletions examples/indent.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,61 @@
use chumsky::prelude::*;
use chumsky::pratt::*;

#[derive(Clone, Debug)]
pub enum Expr {
Add(Box<Self>, Box<Self>),
Sub(Box<Self>, Box<Self>),
Mul(Box<Self>, Box<Self>),
Div(Box<Self>, Box<Self>),
Pow(Box<Self>, Box<Self>),
Neg(Box<Self>),
Factorial(Box<Self>),
Deref(Box<Self>),
Literal(i32),
}

#[derive(Clone, Debug)]
pub enum Stmt {
Expr,
Expr(Expr),
Loop(Vec<Stmt>),
}

fn parser<'a>() -> impl Parser<'a, &'a str, Vec<Stmt>> {
let expr = just("expr"); // TODO
fn parser() -> impl Parser<'static, &'static str, Vec<Stmt>> {
let atom = text::int(10)
.from_str()
.unwrapped()
.map(Expr::Literal)
.padded();

let op = |c| just(c).padded();

let expr = atom.pratt((
postfix(5, op('!'), |lhs, _, _| Expr::Factorial(Box::new(lhs))),
infix(right(4), op('^'), |l, _, r, _| Expr::Pow(Box::new(l), Box::new(r))),
prefix(3, op('-'), |_, rhs, _| Expr::Neg(Box::new(rhs))),
prefix(3, op('*'), |_, rhs, _| Expr::Deref(Box::new(rhs))),
infix(left(1), op('+'), |l, _, r, _| Expr::Add(Box::new(l), Box::new(r))),
infix(left(1), op('-'), |l, _, r, _| Expr::Sub(Box::new(l), Box::new(r))),
infix(left(2), op('*'), |l, _, r, _| Expr::Mul(Box::new(l), Box::new(r))),
infix(left(2), op('/'), |l, _, r, _| Expr::Div(Box::new(l), Box::new(r))),
));

let block = recursive(|block| {
let indent = just(' ')
.repeated()
.configure(|cfg, parent_indent| cfg.exactly(*parent_indent));

let expr_stmt = expr.then_ignore(text::newline()).to(Stmt::Expr);

let expr_stmt = expr
.then_ignore(text::newline().or_not())
.map(Stmt::Expr);

let control_flow = just("loop:")
.then(text::newline())
.ignore_then(block)
.map(Stmt::Loop);
let stmt = expr_stmt.or(control_flow);

let stmt = control_flow.or(expr_stmt);

text::whitespace()
.count()
Expand All @@ -32,17 +68,14 @@ fn parser<'a>() -> impl Parser<'a, &'a str, Vec<Stmt>> {
fn main() {
let stmts = parser().padded().parse(
r#"
expr
expr

loop:
expr
loop:
expr
expr
expr
expr
*1 + -2 * 3!
loop:
10

"#,
);
println!("{:#?}", stmts.output());
println!("{:?}", stmts.errors().collect::<Vec<_>>());
println!("Parsed statements:\n{:?}", stmts.output().unwrap());
println!("Errors:\n{:?}", stmts.errors().collect::<Vec<_>>());
}