[parser] ListParser can handle lists of more than 2 elements 😮

As ListParser sees items within its list, it assembles a vector of Pairs. When
the parser encounters ')', it assembles the pairs into an actual linked list and
returns the root Pair.

This work also revealed that I was asserting incorrectly in my single_pair test.
It should return Null instead of an empty Pair. Neat.

Closes #17.
This commit is contained in:
Eryn Wells 2018-08-26 22:24:17 -07:00
parent c02706e36f
commit c14c939ad3
2 changed files with 29 additions and 24 deletions

View file

@ -10,13 +10,24 @@ use parsers::sym::SymParser;
#[derive(Debug)] #[derive(Debug)]
pub struct ListParser { pub struct ListParser {
list: Option<Pair> pairs: Option<Vec<Pair>>
} }
impl ListParser { impl ListParser {
pub fn new() -> ListParser { pub fn new() -> ListParser {
ListParser { ListParser { pairs: None }
list: None }
fn assemble(&mut self) -> Result<Obj, String> {
match self.pairs.take() {
Some(pairs) => {
let obj = pairs.into_iter().rfold(Obj::Null, |acc, mut pair| {
pair.cdr = acc;
Obj::Ptr(Box::new(pair))
});
Ok(obj)
},
None => Err("bad".to_string())
} }
} }
} }
@ -29,33 +40,35 @@ impl NodeParser for ListParser {
NodeParseResult::Push { next: Box::new(parser) } NodeParseResult::Push { next: Box::new(parser) }
} }
Token::LeftParen => { Token::LeftParen => {
match self.list { match self.pairs {
None => { None => {
// Create our empty pair and proceed parsing this list. // Create our empty pair and proceed parsing this list.
self.list = Some(Pair::empty()); self.pairs = Some(Vec::new());
NodeParseResult::Continue NodeParseResult::Continue
}, },
Some(_) => { Some(_) => {
// This is an embedded list. Create a new parser for it. // This is an embedded list. Create a new parser for it.
let parser = ListParser::new(); let next = Box::new(ListParser::new());
NodeParseResult::Push { next: Box::new(parser) } NodeParseResult::Push { next }
} }
} }
}, },
Token::Id => { Token::Id => {
let parser = SymParser{}; let next = Box::new(SymParser{});
NodeParseResult::Push { next: Box::new(parser) } NodeParseResult::Push { next }
}, },
Token::RightParen => { Token::RightParen => {
match self.list { match self.pairs {
None => { None => {
let msg = format!("Found right paren without matching left paren"); let msg = format!("Found right paren without matching left paren");
NodeParseResult::error(msg) NodeParseResult::error(msg)
}, },
Some(_) => { Some(_) => {
let taken = self.list.take().unwrap(); let list = self.assemble();
// TODO: If the cdr is Null, fill it in with an empty pair. match list {
NodeParseResult::Complete { obj: Obj::new(taken) } Ok(list) => NodeParseResult::Complete { obj: list },
Err(msg) => NodeParseResult::error(msg)
}
} }
} }
} }
@ -68,16 +81,8 @@ impl NodeParser for ListParser {
} }
fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult { fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult {
if let Some(ref mut list) = self.list { if let Some(ref mut pairs) = self.pairs {
match list.car { pairs.push(Pair::with_car(obj));
Obj::Null => {
list.car = obj;
},
Obj::Ptr(_) => {
let pair = Pair::with_car(obj);
list.cdr = Obj::new(pair);
}
}
NodeParseResult::Continue NodeParseResult::Continue
} else { } else {
let msg = format!("what happened here???"); let msg = format!("what happened here???");

View file

@ -27,7 +27,7 @@ fn single_pair() {
let tokens = vec![Ok(Lex::new(Token::LeftParen, "(", 0, 0)), let tokens = vec![Ok(Lex::new(Token::LeftParen, "(", 0, 0)),
Ok(Lex::new(Token::RightParen, ")", 0, 0))].into_iter(); Ok(Lex::new(Token::RightParen, ")", 0, 0))].into_iter();
let mut parser = Parser::new(tokens); let mut parser = Parser::new(tokens);
assert_eq!(parser.next(), Some(Ok(Obj::new(Pair::empty())))); assert_eq!(parser.next(), Some(Ok(Obj::Null)));
assert_eq!(parser.next(), None); assert_eq!(parser.next(), None);
} }