From 929846152e297d5d95f7e2b363ccc5b00846078d Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Thu, 23 Aug 2018 17:52:56 -0700 Subject: [PATCH] [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 --- parser/src/lib.rs | 9 ++++--- parser/src/list_parser.rs | 37 +++++++++++++++++++++++++++ parser/src/node_parser.rs | 53 ++++++--------------------------------- parser/src/sym_parser.rs | 27 ++++++++++++++++++++ types/src/bool.rs | 24 ++++++++++++------ types/src/object.rs | 13 +++++++++- types/src/pair.rs | 10 ++++++++ types/src/sym.rs | 12 +++++++++ 8 files changed, 129 insertions(+), 56 deletions(-) create mode 100644 parser/src/list_parser.rs create mode 100644 parser/src/sym_parser.rs diff --git a/parser/src/lib.rs b/parser/src/lib.rs index e8517e2..6fb79d5 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -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; +pub type Result = std::result::Result; #[derive(Debug)] pub struct ParseError; diff --git a/parser/src/list_parser.rs b/parser/src/list_parser.rs new file mode 100644 index 0000000..9997a32 --- /dev/null +++ b/parser/src/list_parser.rs @@ -0,0 +1,37 @@ +/* parser/src/list_parser.rs + * Eryn Wells + */ + +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() } + } + } +} diff --git a/parser/src/node_parser.rs b/parser/src/node_parser.rs index 15ee573..fdd2af4 100644 --- a/parser/src/node_parser.rs +++ b/parser/src/node_parser.rs @@ -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 }, @@ -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() } - } -} diff --git a/parser/src/sym_parser.rs b/parser/src/sym_parser.rs new file mode 100644 index 0000000..0b47c8f --- /dev/null +++ b/parser/src/sym_parser.rs @@ -0,0 +1,27 @@ +/* parser/src/sym_parser.rs + * Eryn Wells + */ + +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) + } + } + } +} diff --git a/types/src/bool.rs b/types/src/bool.rs index 6655df4..88bc9a6 100644 --- a/types/src/bool.rs +++ b/types/src/bool.rs @@ -2,18 +2,28 @@ * Eryn Wells */ -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; diff --git a/types/src/object.rs b/types/src/object.rs index 2a26aac..2212494 100644 --- a/types/src/object.rs +++ b/types/src/object.rs @@ -23,7 +23,8 @@ pub enum Obj { } pub trait Object: - fmt::Display + fmt::Debug + + fmt::Display { fn as_any(&self) -> &Any; fn as_pair(&self) -> Option<&Pair>; @@ -31,6 +32,10 @@ pub trait Object: } impl Obj { + pub fn new(obj: T) -> Obj { + Obj::Ptr(Box::new(obj)) + } + pub fn unbox_as(&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), diff --git a/types/src/pair.rs b/types/src/pair.rs index 039d61f..9ffb567 100644 --- a/types/src/pair.rs +++ b/types/src/pair.rs @@ -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) + } +} diff --git a/types/src/sym.rs b/types/src/sym.rs index 4ab1782..eedeacd 100644 --- a/types/src/sym.rs +++ b/types/src/sym.rs @@ -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) + } +}