[parser] Add subparser_completed() method to NodeParser and implementing Parsers

This commit is contained in:
Eryn Wells 2018-08-24 21:06:24 -07:00
parent 0a9f235836
commit d3520be67e
4 changed files with 53 additions and 15 deletions

View file

@ -9,13 +9,13 @@ use sym_parser::SymParser;
#[derive(Debug)] #[derive(Debug)]
pub struct ListParser { pub struct ListParser {
list: Obj list: Option<Pair>
} }
impl ListParser { impl ListParser {
pub fn new() -> ListParser { pub fn new() -> ListParser {
ListParser { ListParser {
list: Obj::Null list: None
} }
} }
} }
@ -25,12 +25,12 @@ impl NodeParser for ListParser {
match lex.token() { match lex.token() {
Token::LeftParen => { Token::LeftParen => {
match self.list { match self.list {
Obj::Null => { None => {
// Create our empty pair and proceed parsing this list. // Create our empty pair and proceed parsing this list.
self.list = Obj::new(Pair::empty()); self.list = Some(Pair::empty());
NodeParseResult::Continue NodeParseResult::Continue
}, },
Obj::Ptr(_) => { 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 parser = ListParser::new();
NodeParseResult::Push { next: Box::new(parser) } NodeParseResult::Push { next: Box::new(parser) }
@ -42,7 +42,17 @@ impl NodeParser for ListParser {
NodeParseResult::Push { next: Box::new(parser) } NodeParseResult::Push { next: Box::new(parser) }
}, },
Token::RightParen => { Token::RightParen => {
NodeParseResult::Complete { obj: self.list.take() } match self.list {
None => {
let msg = format!("Found right paren without matching left paren");
NodeParseResult::error(msg)
},
Some(_) => {
let taken = self.list.take().unwrap();
// TODO: If the cdr is Null, fill it in with an empty pair.
NodeParseResult::Complete { obj: Obj::new(taken) }
}
}
} }
} }
} }
@ -51,4 +61,22 @@ impl NodeParser for ListParser {
let msg = format!("Unmatched paren, found EOF"); let msg = format!("Unmatched paren, found EOF");
NodeParseResult::error(msg) NodeParseResult::error(msg)
} }
fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult {
if let Some(ref mut list) = self.list {
match list.car {
Obj::Null => {
list.car = obj;
},
Obj::Ptr(_) => {
let pair = Pair::with_car(obj);
list.cdr = Obj::new(pair);
}
}
NodeParseResult::Continue
} else {
let msg = format!("what happened here???");
NodeParseResult::error(msg)
}
}
} }

View file

@ -10,11 +10,9 @@ use sibiltypes::Obj;
pub enum NodeParseResult { pub enum NodeParseResult {
/// Continue parsing with this NodeParser. The passed in Lex was consumed. /// Continue parsing with this NodeParser. The passed in Lex was consumed.
Continue, Continue,
/// This NodeParser has completed its work and has produced the given Object /// This NodeParser has completed its work and has produced the given Object as a result.
/// as a result.
Complete { obj: Obj }, Complete { obj: Obj },
/// Push a new NodeParser onto the parsing stack and let that parser proceed /// Push a new NodeParser onto the parsing stack and let that parser proceed with the current Lex.
/// with the current Lex.
Push { next: Box<NodeParser> }, Push { next: Box<NodeParser> },
/// There was an error parsing with the current Lex. /// There was an error parsing with the current Lex.
Error { msg: String }, Error { msg: String },
@ -26,13 +24,16 @@ impl NodeParseResult {
} }
} }
/// A `NodeParser` is responsible for parsing one particular thing in the Scheme /// A `NodeParser` is responsible for parsing one particular thing in the Scheme parse tree.
/// parse tree. Roughly, there should be one `XParser` for each variant of the /// Roughly, there should be one NodeParser for each type of object in `sibiltypes`. As the
/// `sibiltypes::Object` enum. As the top-level `Parser` object progresses /// top-level `Parser` object progresses through the stream of tokens, new NodeParsers are created
/// through the stream of tokens, new NodeParsers are created to handle the /// to handle the nodes it encounters.
/// nodes it encounters.
pub trait NodeParser: Debug { pub trait NodeParser: Debug {
/// Called on a NodeParser when a Lex is encountered in the input.
fn parse(&mut self, lex: &Lex) -> NodeParseResult; fn parse(&mut self, lex: &Lex) -> NodeParseResult;
/// Called on a NodeParser when None is encountered in the input. /// Called on a NodeParser when None is encountered in the input.
fn none(&mut self) -> NodeParseResult; fn none(&mut self) -> NodeParseResult;
/// Called on a NodeParser when a NodeParser created by this one returns an object via
/// `NodeParseResult::Complete`.
fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult;
} }

View file

@ -40,5 +40,9 @@ impl NodeParser for ProgramParser {
fn none(&mut self) -> NodeParseResult { fn none(&mut self) -> NodeParseResult {
NodeParseResult::Complete { obj: Obj::Null } NodeParseResult::Complete { obj: Obj::Null }
} }
fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult {
NodeParseResult::Complete { obj: obj }
}
} }

View file

@ -29,4 +29,9 @@ impl NodeParser for SymParser {
let msg = format!("Expected symbol, found EOF"); let msg = format!("Expected symbol, found EOF");
NodeParseResult::error(msg) NodeParseResult::error(msg)
} }
fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult {
let msg = format!("Unexpected parser result: {}", obj);
NodeParseResult::error(msg)
}
} }