[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:
parent
c02706e36f
commit
c14c939ad3
2 changed files with 29 additions and 24 deletions
|
@ -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???");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue