[parser, types] Clean up obj parsers
- Define ListParser, SymParser in their own separate modules - Add some stuff to types to make working with them more ergonomic
This commit is contained in:
		
							parent
							
								
									b6a9b8a855
								
							
						
					
					
						commit
						929846152e
					
				
					 8 changed files with 129 additions and 56 deletions
				
			
		| 
						 | 
				
			
			@ -5,15 +5,18 @@
 | 
			
		|||
extern crate sibillexer;
 | 
			
		||||
extern crate sibiltypes;
 | 
			
		||||
 | 
			
		||||
mod list_parser;
 | 
			
		||||
mod node_parser;
 | 
			
		||||
mod sym_parser;
 | 
			
		||||
 | 
			
		||||
use std::iter::Peekable;
 | 
			
		||||
use sibillexer::Result as LexerResult;
 | 
			
		||||
use sibiltypes::Object;
 | 
			
		||||
use node_parser::{NodeParser, IdParser, ListParser};
 | 
			
		||||
use sibiltypes::Obj;
 | 
			
		||||
use node_parser::NodeParser;
 | 
			
		||||
use sym_parser::SymParser;
 | 
			
		||||
 | 
			
		||||
/// The output of calling `parse()` on a Parser is one of these Result objects.
 | 
			
		||||
pub type Result = std::result::Result<Object, ParseError>;
 | 
			
		||||
pub type Result = std::result::Result<Obj, ParseError>;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct ParseError;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										37
									
								
								parser/src/list_parser.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								parser/src/list_parser.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
/* parser/src/list_parser.rs
 | 
			
		||||
 * Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use sibillexer::{Lex, Token};
 | 
			
		||||
use sibiltypes::{Obj, Pair};
 | 
			
		||||
use node_parser::{NodeParser, NodeParseResult};
 | 
			
		||||
use sym_parser::SymParser;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct ListParser {
 | 
			
		||||
    list: Obj
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ListParser {
 | 
			
		||||
    pub fn new() -> ListParser {
 | 
			
		||||
        ListParser {
 | 
			
		||||
            list: Obj::Null
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NodeParser for ListParser {
 | 
			
		||||
    fn parse(&mut self, lex: Lex) -> NodeParseResult {
 | 
			
		||||
        match lex.token() {
 | 
			
		||||
            Token::LeftParen => {
 | 
			
		||||
                self.list = Obj::new(Pair::empty());
 | 
			
		||||
                NodeParseResult::Continue
 | 
			
		||||
            },
 | 
			
		||||
            Token::Id => {
 | 
			
		||||
                let parser = SymParser{};
 | 
			
		||||
                NodeParseResult::Push { next: Box::new(parser) }
 | 
			
		||||
            }
 | 
			
		||||
            _ => NodeParseResult::Error { msg: "womp".to_string() }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,7 @@
 | 
			
		|||
 | 
			
		||||
use std::fmt::Debug;
 | 
			
		||||
use sibillexer::{Lex, Token};
 | 
			
		||||
use sibiltypes::{Object, ObjectPtr};
 | 
			
		||||
use sibiltypes::Obj;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum NodeParseResult {
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ pub enum NodeParseResult {
 | 
			
		|||
    Continue,
 | 
			
		||||
    /// This NodeParser has completed its work and has produced the given Object
 | 
			
		||||
    /// as a result.
 | 
			
		||||
    Complete { obj: ObjectPtr },
 | 
			
		||||
    Complete { obj: Obj },
 | 
			
		||||
    /// Push a new NodeParser onto the parsing stack and let that parser proceed
 | 
			
		||||
    /// with the current Lex.
 | 
			
		||||
    Push { next: Box<NodeParser> },
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +20,12 @@ pub enum NodeParseResult {
 | 
			
		|||
    Error { msg: String },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NodeParseResult {
 | 
			
		||||
    pub fn error(msg: String) -> NodeParseResult {
 | 
			
		||||
        NodeParseResult::Error { msg: msg }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// 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
 | 
			
		||||
| 
						 | 
				
			
			@ -45,47 +51,4 @@ impl NodeParser for ProgramParser {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct IdParser {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IdParser {
 | 
			
		||||
    pub fn new() -> IdParser {
 | 
			
		||||
        IdParser { }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NodeParser for IdParser {
 | 
			
		||||
    fn parse(&mut self, lex: Lex) -> NodeParseResult {
 | 
			
		||||
        match lex.token() {
 | 
			
		||||
            Token::Id => {
 | 
			
		||||
                let value = String::from(lex.value());
 | 
			
		||||
                let obj = ObjectPtr::new(Object::Symbol(value));
 | 
			
		||||
                NodeParseResult::Complete { obj: obj }
 | 
			
		||||
            }
 | 
			
		||||
            _ => {
 | 
			
		||||
                let msg = String::from(format!("Invalid token: {:?}", lex));
 | 
			
		||||
                NodeParseResult::Error { msg: msg }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct ListParser {
 | 
			
		||||
    list: ObjectPtr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ListParser {
 | 
			
		||||
    pub fn new() -> ListParser {
 | 
			
		||||
        ListParser {
 | 
			
		||||
            list: ObjectPtr::Null
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl NodeParser for ListParser {
 | 
			
		||||
    fn parse(&mut self, lex: Lex) -> NodeParseResult {
 | 
			
		||||
        NodeParseResult::Error { msg: "womp".to_string() }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								parser/src/sym_parser.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								parser/src/sym_parser.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
/* parser/src/sym_parser.rs
 | 
			
		||||
 * Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use sibillexer::{Lex, Token};
 | 
			
		||||
use sibiltypes::{Obj, Sym};
 | 
			
		||||
use node_parser::{NodeParser, NodeParseResult};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct SymParser;
 | 
			
		||||
 | 
			
		||||
impl NodeParser for SymParser {
 | 
			
		||||
    fn parse(&mut self, lex: Lex) -> NodeParseResult {
 | 
			
		||||
        match lex.token() {
 | 
			
		||||
            Token::Id => {
 | 
			
		||||
                let value = String::from(lex.value());
 | 
			
		||||
                // Initializing with Sym(value) caused E0423. So use this isntead.
 | 
			
		||||
                let obj = Obj::new(Sym::new(value));
 | 
			
		||||
                NodeParseResult::Complete { obj: obj }
 | 
			
		||||
            }
 | 
			
		||||
            _ => {
 | 
			
		||||
                let msg = format!("Invalid token: {:?}", lex);
 | 
			
		||||
                NodeParseResult::error(msg)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,18 +2,28 @@
 | 
			
		|||
 * Eryn Wells <eryn@erynwells.me>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use object::Object;
 | 
			
		||||
use predicates::IsBool;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use object::Obj;
 | 
			
		||||
use preds;
 | 
			
		||||
 | 
			
		||||
impl IsBool for Object {
 | 
			
		||||
    fn is_bool(&self) -> bool {
 | 
			
		||||
        match *self {
 | 
			
		||||
            Object::Bool(_) => true,
 | 
			
		||||
            _ => false,
 | 
			
		||||
/// The Scheme boolean type. It can be `True` or `False`.
 | 
			
		||||
pub enum Bool { True, False }
 | 
			
		||||
 | 
			
		||||
impl Obj for Bool { }
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for Bool {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            Bool::True => write!(f, "#t"),
 | 
			
		||||
            Bool::False => write!(f, "#f")
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl preds::IsBool for Bool {
 | 
			
		||||
    fn is_bool(&self) -> bool { true }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use object::Object;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ pub enum Obj {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
pub trait Object:
 | 
			
		||||
    fmt::Debug +
 | 
			
		||||
    fmt::Display
 | 
			
		||||
{
 | 
			
		||||
    fn as_any(&self) -> &Any;
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +32,10 @@ pub trait Object:
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
impl Obj {
 | 
			
		||||
    pub fn new<T: 'static + Object>(obj: T) -> Obj {
 | 
			
		||||
        Obj::Ptr(Box::new(obj))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn unbox_as<T: 'static + Object>(&self) -> Option<&T> {
 | 
			
		||||
        match self {
 | 
			
		||||
            Obj::Null => None,
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +53,12 @@ impl fmt::Display for Obj {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Debug for Obj {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
        write!(f, "{}", self)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//#[derive(Debug, PartialEq)]
 | 
			
		||||
//pub enum Object {
 | 
			
		||||
//    ByteVector(Vec<u8>),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,10 @@ pub struct Pair {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
impl Pair {
 | 
			
		||||
    pub fn empty() -> Pair {
 | 
			
		||||
        Pair { car: Obj::Null, cdr: Obj::Null }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn fmt_pair(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
        let r = write!(f, "{}", self.car);
 | 
			
		||||
        r.and_then(|r| match self.cdr {
 | 
			
		||||
| 
						 | 
				
			
			@ -39,3 +43,9 @@ impl fmt::Display for Pair {
 | 
			
		|||
                      .and_then(|_| write!(f, ")"))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Debug for Pair {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
        write!(f, "{}", self)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,12 @@ use super::*;
 | 
			
		|||
 | 
			
		||||
pub struct Sym(String);
 | 
			
		||||
 | 
			
		||||
impl Sym {
 | 
			
		||||
    pub fn new(value: String) -> Sym {
 | 
			
		||||
        Sym(value)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Object for Sym {
 | 
			
		||||
    fn as_any(&self) -> &Any { self }
 | 
			
		||||
    fn as_pair(&self) -> Option<&Pair> { None }
 | 
			
		||||
| 
						 | 
				
			
			@ -20,3 +26,9 @@ impl fmt::Display for Sym {
 | 
			
		|||
        write!(f, "{}", self.0)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Debug for Sym {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
			
		||||
        write!(f, "{}", self)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue