[parser] Add subparser_completed() method to NodeParser and implementing Parsers
This commit is contained in:
parent
0a9f235836
commit
d3520be67e
4 changed files with 53 additions and 15 deletions
|
@ -9,13 +9,13 @@ use sym_parser::SymParser;
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ListParser {
|
||||
list: Obj
|
||||
list: Option<Pair>
|
||||
}
|
||||
|
||||
impl ListParser {
|
||||
pub fn new() -> ListParser {
|
||||
ListParser {
|
||||
list: Obj::Null
|
||||
list: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,12 +25,12 @@ impl NodeParser for ListParser {
|
|||
match lex.token() {
|
||||
Token::LeftParen => {
|
||||
match self.list {
|
||||
Obj::Null => {
|
||||
None => {
|
||||
// Create our empty pair and proceed parsing this list.
|
||||
self.list = Obj::new(Pair::empty());
|
||||
self.list = Some(Pair::empty());
|
||||
NodeParseResult::Continue
|
||||
},
|
||||
Obj::Ptr(_) => {
|
||||
Some(_) => {
|
||||
// This is an embedded list. Create a new parser for it.
|
||||
let parser = ListParser::new();
|
||||
NodeParseResult::Push { next: Box::new(parser) }
|
||||
|
@ -42,7 +42,17 @@ impl NodeParser for ListParser {
|
|||
NodeParseResult::Push { next: Box::new(parser) }
|
||||
},
|
||||
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");
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,11 +10,9 @@ use sibiltypes::Obj;
|
|||
pub enum NodeParseResult {
|
||||
/// Continue parsing with this NodeParser. The passed in Lex was consumed.
|
||||
Continue,
|
||||
/// This NodeParser has completed its work and has produced the given Object
|
||||
/// as a result.
|
||||
/// This NodeParser has completed its work and has produced the given Object as a result.
|
||||
Complete { obj: Obj },
|
||||
/// Push a new NodeParser onto the parsing stack and let that parser proceed
|
||||
/// with the current Lex.
|
||||
/// Push a new NodeParser onto the parsing stack and let that parser proceed with the current Lex.
|
||||
Push { next: Box<NodeParser> },
|
||||
/// There was an error parsing with the current Lex.
|
||||
Error { msg: String },
|
||||
|
@ -26,13 +24,16 @@ impl NodeParseResult {
|
|||
}
|
||||
}
|
||||
|
||||
/// A `NodeParser` is responsible for parsing one particular thing in the Scheme
|
||||
/// parse tree. Roughly, there should be one `XParser` for each variant of the
|
||||
/// `sibiltypes::Object` enum. As the top-level `Parser` object progresses
|
||||
/// through the stream of tokens, new NodeParsers are created to handle the
|
||||
/// nodes it encounters.
|
||||
/// A `NodeParser` is responsible for parsing one particular thing in the Scheme parse tree.
|
||||
/// Roughly, there should be one NodeParser for each type of object in `sibiltypes`. As the
|
||||
/// top-level `Parser` object progresses through the stream of tokens, new NodeParsers are created
|
||||
/// to handle the nodes it encounters.
|
||||
pub trait NodeParser: Debug {
|
||||
/// Called on a NodeParser when a Lex is encountered in the input.
|
||||
fn parse(&mut self, lex: &Lex) -> NodeParseResult;
|
||||
/// Called on a NodeParser when None is encountered in the input.
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -40,5 +40,9 @@ impl NodeParser for ProgramParser {
|
|||
fn none(&mut self) -> NodeParseResult {
|
||||
NodeParseResult::Complete { obj: Obj::Null }
|
||||
}
|
||||
|
||||
fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult {
|
||||
NodeParseResult::Complete { obj: obj }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,4 +29,9 @@ impl NodeParser for SymParser {
|
|||
let msg = format!("Expected symbol, found EOF");
|
||||
NodeParseResult::error(msg)
|
||||
}
|
||||
|
||||
fn subparser_completed(&mut self, obj: Obj) -> NodeParseResult {
|
||||
let msg = format!("Unexpected parser result: {}", obj);
|
||||
NodeParseResult::error(msg)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue