Sexp parser

This commit is contained in:
Greg Shuflin 2024-01-29 04:08:32 -08:00
parent 51d7380761
commit d8a68bcbf3
2 changed files with 27 additions and 1 deletions

View File

@ -107,6 +107,19 @@ where
allow_trailing: bool, allow_trailing: bool,
} }
impl<D, P, I, O, E> SeparatedBy<D, P, I, O, E>
where
D: Parser<I, (), E>,
P: Parser<I, O, E>,
E: Default,
{
pub fn allow_trailing(self, allow_trailing: bool) -> Self {
Self {
allow_trailing,
..self
}
}
}
impl<D, P, I, O, E> Parser<I, Vec<O>, E> for SeparatedBy<D, P, I, O, E> impl<D, P, I, O, E> Parser<I, Vec<O>, E> for SeparatedBy<D, P, I, O, E>
where where
D: Parser<I, (), E>, D: Parser<I, (), E>,

View File

@ -53,7 +53,11 @@ fn parse_expr(input: &str) -> ParseResult<&str, Expr, ()> {
fn parse_list(input: &str) -> ParseResult<&str, Expr, ()> { fn parse_list(input: &str) -> ParseResult<&str, Expr, ()> {
literal_char('(') literal_char('(')
.ignore_then(repeated(parse_atom.map(Expr::Atom)).separated_by(whitespace.to(()))) .ignore_then(
repeated(parse_expr)
.separated_by(repeated(whitespace).at_least(1).to(()))
.allow_trailing(true),
)
.then_ignore(literal_char(')')) .then_ignore(literal_char(')'))
.map(Expr::List) .map(Expr::List)
.parse(input) .parse(input)
@ -71,4 +75,13 @@ fn test_parse_sexp() {
]) ])
); );
assert_eq!(output.1, ""); assert_eq!(output.1, "");
let complex_input = r#"
(add (mul 28 9)
(if (eq a b) (jump #t) (hula 44))
)"#
.trim();
let output = parse_expr(complex_input).unwrap();
assert_eq!(output.1, "");
} }