[parser] Handle dotted pairs!

This commit is contained in:
Eryn Wells 2018-09-08 16:06:23 -07:00
parent fe271dfd8b
commit c6696c4f8b
4 changed files with 60 additions and 15 deletions

View file

@ -10,20 +10,25 @@ use parsers::sym::SymParser;
#[derive(Debug)] #[derive(Debug)]
pub struct ListParser { pub struct ListParser {
pairs: Option<Vec<Pair>> pairs: Option<Vec<Pair>>,
waiting_for_final: bool,
} }
impl ListParser { impl ListParser {
pub fn new() -> ListParser { pub fn new() -> ListParser {
ListParser { pairs: None } ListParser {
pairs: None,
waiting_for_final: false,
}
} }
fn assemble(&mut self) -> Result<Obj, String> { fn assemble(&mut self) -> Result<Obj, String> {
match self.pairs.take() { match self.pairs.take() {
Some(pairs) => { Some(mut pairs) => {
let obj = pairs.into_iter().rfold(Obj::Null, |acc, mut pair| { 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; pair.cdr = acc;
Obj::Ptr(Box::new(pair)) Obj::new(pair)
}); });
Ok(obj) Ok(obj)
}, },
@ -38,7 +43,11 @@ impl NodeParser for ListParser {
Token::Bool(_) => { Token::Bool(_) => {
let parser = BoolParser{}; let parser = BoolParser{};
NodeParseResult::Push { next: Box::new(parser) } NodeParseResult::Push { next: Box::new(parser) }
} },
Token::Dot => {
self.waiting_for_final = true;
NodeParseResult::Continue
},
Token::LeftParen => { Token::LeftParen => {
match self.pairs { match self.pairs {
None => { None => {
@ -57,6 +66,12 @@ impl NodeParser for ListParser {
let next = Box::new(SymParser{}); let next = Box::new(SymParser{});
NodeParseResult::Push { next } NodeParseResult::Push { next }
}, },
Token::Num(n) => {
panic!("TODO: Handle numbrs.");
},
Token::Quote => {
panic!("TODO: Handle quotes.");
},
Token::RightParen => { Token::RightParen => {
match self.pairs { match self.pairs {
None => { 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 { fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult {
if let Some(ref mut pairs) = self.pairs { match self.pairs {
pairs.push(Pair::with_car(obj)); Some(ref mut pairs) if self.waiting_for_final => match pairs.last_mut() {
NodeParseResult::Continue Some(ref mut last) => {
} else { last.cdr = obj;
let msg = format!("what happened here???"); // Waiting for RightParen to close list.
NodeParseResult::error(msg) 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)
},
} }
} }
} }

View file

@ -37,7 +37,10 @@ impl NodeParser for ProgramParser {
let parser = SymParser{}; let parser = SymParser{};
let parser = Box::new(parser); let parser = Box::new(parser);
NodeParseResult::Push { next: parser } NodeParseResult::Push { next: parser }
} },
_ => {
panic!("unhandled symbol");
},
} }
} }

View file

@ -32,3 +32,16 @@ fn list_of_four_tokens() {
assert_eq!(parser.next(), Some(Ok(ex_list))); assert_eq!(parser.next(), Some(Ok(ex_list)));
assert_eq!(parser.next(), None); 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);
}

View file

@ -11,7 +11,7 @@ extern crate sibiltypes;
use sibillexer::{Lex, Token}; use sibillexer::{Lex, Token};
use sibillexer::Result as LexerResult; use sibillexer::Result as LexerResult;
use sibilparser::Parser; use sibilparser::Parser;
use sibiltypes::{Bool, Obj, Pair, Sym}; use sibiltypes::{Bool, Obj, Sym};
#[test] #[test]
fn single_sym() { fn single_sym() {