[parser] Handle dotted pairs!
This commit is contained in:
parent
fe271dfd8b
commit
c6696c4f8b
4 changed files with 60 additions and 15 deletions
|
@ -10,20 +10,25 @@ use parsers::sym::SymParser;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ListParser {
|
||||
pairs: Option<Vec<Pair>>
|
||||
pairs: Option<Vec<Pair>>,
|
||||
waiting_for_final: bool,
|
||||
}
|
||||
|
||||
impl ListParser {
|
||||
pub fn new() -> ListParser {
|
||||
ListParser { pairs: None }
|
||||
ListParser {
|
||||
pairs: None,
|
||||
waiting_for_final: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble(&mut self) -> Result<Obj, String> {
|
||||
match self.pairs.take() {
|
||||
Some(pairs) => {
|
||||
let obj = pairs.into_iter().rfold(Obj::Null, |acc, mut pair| {
|
||||
Some(mut pairs) => {
|
||||
let last = pairs.last_mut().and_then(|p| Some(p.cdr.take())).unwrap_or(Obj::Null);
|
||||
let obj = pairs.into_iter().rfold(last, |acc, mut pair| {
|
||||
pair.cdr = acc;
|
||||
Obj::Ptr(Box::new(pair))
|
||||
Obj::new(pair)
|
||||
});
|
||||
Ok(obj)
|
||||
},
|
||||
|
@ -38,7 +43,11 @@ impl NodeParser for ListParser {
|
|||
Token::Bool(_) => {
|
||||
let parser = BoolParser{};
|
||||
NodeParseResult::Push { next: Box::new(parser) }
|
||||
}
|
||||
},
|
||||
Token::Dot => {
|
||||
self.waiting_for_final = true;
|
||||
NodeParseResult::Continue
|
||||
},
|
||||
Token::LeftParen => {
|
||||
match self.pairs {
|
||||
None => {
|
||||
|
@ -57,6 +66,12 @@ impl NodeParser for ListParser {
|
|||
let next = Box::new(SymParser{});
|
||||
NodeParseResult::Push { next }
|
||||
},
|
||||
Token::Num(n) => {
|
||||
panic!("TODO: Handle numbrs.");
|
||||
},
|
||||
Token::Quote => {
|
||||
panic!("TODO: Handle quotes.");
|
||||
},
|
||||
Token::RightParen => {
|
||||
match self.pairs {
|
||||
None => {
|
||||
|
@ -71,7 +86,7 @@ impl NodeParser for ListParser {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,12 +96,26 @@ impl NodeParser for ListParser {
|
|||
}
|
||||
|
||||
fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult {
|
||||
if let Some(ref mut pairs) = self.pairs {
|
||||
pairs.push(Pair::with_car(obj));
|
||||
NodeParseResult::Continue
|
||||
} else {
|
||||
let msg = format!("what happened here???");
|
||||
NodeParseResult::error(msg)
|
||||
match self.pairs {
|
||||
Some(ref mut pairs) if self.waiting_for_final => match pairs.last_mut() {
|
||||
Some(ref mut last) => {
|
||||
last.cdr = obj;
|
||||
// Waiting for RightParen to close list.
|
||||
NodeParseResult::Continue
|
||||
},
|
||||
None => {
|
||||
let msg = "Found dot before any pairs parsed".to_string();
|
||||
NodeParseResult::error(msg)
|
||||
},
|
||||
},
|
||||
Some(ref mut pairs) => {
|
||||
pairs.push(Pair::with_car(obj));
|
||||
NodeParseResult::Continue
|
||||
},
|
||||
None => {
|
||||
let msg = "While attempting to parse list, found token before opening paren".to_string();
|
||||
NodeParseResult::error(msg)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,10 @@ impl NodeParser for ProgramParser {
|
|||
let parser = SymParser{};
|
||||
let parser = Box::new(parser);
|
||||
NodeParseResult::Push { next: parser }
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
panic!("unhandled symbol");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,3 +32,16 @@ fn list_of_four_tokens() {
|
|||
assert_eq!(parser.next(), Some(Ok(ex_list)));
|
||||
assert_eq!(parser.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_dotted_pair() {
|
||||
let tokens = vec![Ok(Lex::new(Token::LeftParen, "(", 0, 0)),
|
||||
Ok(Lex::new(Token::Id, "ab", 0, 0)),
|
||||
Ok(Lex::new(Token::Dot, ".", 0, 0)),
|
||||
Ok(Lex::new(Token::Id, "cd", 0, 0)),
|
||||
Ok(Lex::new(Token::RightParen, ")", 0, 0))].into_iter();
|
||||
let mut parser = Parser::new(tokens);
|
||||
let ex_list = Obj::new(Pair::new(Obj::new(Sym::with_str("ab")), Obj::new(Sym::with_str("cd"))));
|
||||
assert_eq!(parser.next(), Some(Ok(ex_list)));
|
||||
assert_eq!(parser.next(), None);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ extern crate sibiltypes;
|
|||
use sibillexer::{Lex, Token};
|
||||
use sibillexer::Result as LexerResult;
|
||||
use sibilparser::Parser;
|
||||
use sibiltypes::{Bool, Obj, Pair, Sym};
|
||||
use sibiltypes::{Bool, Obj, Sym};
|
||||
|
||||
#[test]
|
||||
fn single_sym() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue