Parse list before dotted pair

This commit is contained in:
Vincent Ollivier 2022-10-28 18:44:54 +02:00
parent db8c088ea4
commit 6c5fef42a8
1 changed files with 13 additions and 6 deletions

View File

@ -18,6 +18,7 @@ use nom::combinator::opt;
use nom::combinator::recognize;
use nom::combinator::value;
use nom::multi::many0;
use nom::multi::many1;
use nom::sequence::delimited;
use nom::sequence::preceded;
use nom::sequence::tuple;
@ -62,14 +63,20 @@ fn parse_list(input: &str) -> IResult<&str, Exp> {
Ok((input, Exp::List(list)))
}
fn parse_pair(input: &str) -> IResult<&str, Exp> {
let (input, (car, cdr)) = delimited(
fn parse_dotted_list(input: &str) -> IResult<&str, Exp> {
let (input, (mut list, cdr)) = delimited(
char('('),
separated_pair(parse_exp, char('.'), parse_exp),
separated_pair(many1(parse_exp), char('.'), parse_exp),
char(')')
)(input)?;
let list = vec![Exp::Sym("cons".to_string()), car, cdr];
Ok((input, Exp::List(list)))
let car = list.pop().unwrap();
let cons = Exp::List(vec![Exp::Sym("cons".to_string()), car, cdr]);
if list.is_empty() {
Ok((input, cons))
} else {
list.push(cons);
Ok((input, Exp::List(list)))
}
}
fn parse_quote(input: &str) -> IResult<&str, Exp> {
@ -98,7 +105,7 @@ fn parse_quasiquote(input: &str) -> IResult<&str, Exp> {
fn parse_exp(input: &str) -> IResult<&str, Exp> {
delimited(multispace0, alt((
parse_num, parse_bool, parse_str, parse_list, parse_pair, parse_quote,
parse_num, parse_bool, parse_str, parse_dotted_list, parse_list, parse_quote,
parse_unquote_splicing, parse_unquote, parse_quasiquote, parse_sym
)), multispace0)(input)
}