Skip to content

Instantly share code, notes, and snippets.

@zesterer
Created June 27, 2023 23:57
Show Gist options
  • Save zesterer/e0a896ef16fdc95a4749851ebb0d8461 to your computer and use it in GitHub Desktop.
Save zesterer/e0a896ef16fdc95a4749851ebb0d8461 to your computer and use it in GitHub Desktop.
Chumsky's nested.rs example, but with spans included
use chumsky::{prelude::*, input::SpannedInput};
// This token is a tree: it contains within it a sub-tree of tokens
#[derive(PartialEq, Debug)]
enum Token {
Num(i64),
Add,
Mul,
Parens(Vec<(Token, SimpleSpan)>),
}
type TokenTreeInput<'a> = SpannedInput<Token, SimpleSpan, &'a [(Token, SimpleSpan)]>;
fn parser<'a>(eoi: SimpleSpan) -> impl Parser<'a, TokenTreeInput<'a>, i64> {
recursive(|expr| {
let num = select_ref! { Token::Num(x) => *x };
let parens = expr
// Here we specify how the parser should come up with the nested tokens
.nested_in(select_ref! { Token::Parens(xs) => xs.as_slice().spanned(eoi) });
let atom = num.or(parens);
let product = atom
.clone()
.foldl(just(&Token::Mul).ignore_then(atom).repeated(), |a, b| a * b);
let sum = product
.clone()
.foldl(just(&Token::Add).ignore_then(product).repeated(), |a, b| {
a + b
});
sum
})
}
fn main() {
// This token tree represents the expression `(2 + 3) * 4`
let tokens = [
(Token::Parens(vec![
(Token::Num(2), SimpleSpan::new(1, 2)),
(Token::Add, SimpleSpan::new(3, 4)),
(Token::Num(3), SimpleSpan::new(5, 6)),
]), SimpleSpan::new(0, 7)),
(Token::Mul, SimpleSpan::new(8, 9)),
(Token::Num(4), SimpleSpan::new(10, 11)),
];
let eoi = SimpleSpan::new(11, 11); // Example EoI
assert_eq!(parser(eoi).parse(tokens[..].spanned(eoi)).into_result(), Ok(20));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment