[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:
Eryn Wells 2018-08-23 17:52:56 -07:00
parent b6a9b8a855
commit 929846152e
8 changed files with 129 additions and 56 deletions

View file

@ -5,15 +5,18 @@
extern crate sibillexer; extern crate sibillexer;
extern crate sibiltypes; extern crate sibiltypes;
mod list_parser;
mod node_parser; mod node_parser;
mod sym_parser;
use std::iter::Peekable; use std::iter::Peekable;
use sibillexer::Result as LexerResult; use sibillexer::Result as LexerResult;
use sibiltypes::Object; use sibiltypes::Obj;
use node_parser::{NodeParser, IdParser, ListParser}; use node_parser::NodeParser;
use sym_parser::SymParser;
/// The output of calling `parse()` on a Parser is one of these Result objects. /// 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)] #[derive(Debug)]
pub struct ParseError; pub struct ParseError;

37
parser/src/list_parser.rs Normal file
View 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() }
}
}
}

View file

@ -4,7 +4,7 @@
use std::fmt::Debug; use std::fmt::Debug;
use sibillexer::{Lex, Token}; use sibillexer::{Lex, Token};
use sibiltypes::{Object, ObjectPtr}; use sibiltypes::Obj;
#[derive(Debug)] #[derive(Debug)]
pub enum NodeParseResult { pub enum NodeParseResult {
@ -12,7 +12,7 @@ pub enum NodeParseResult {
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: ObjectPtr }, 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> },
@ -20,6 +20,12 @@ pub enum NodeParseResult {
Error { msg: String }, 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 /// 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 /// parse tree. Roughly, there should be one `XParser` for each variant of the
/// `sibiltypes::Object` enum. As the top-level `Parser` object progresses /// `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
View 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)
}
}
}
}

View file

@ -2,18 +2,28 @@
* Eryn Wells <eryn@erynwells.me> * Eryn Wells <eryn@erynwells.me>
*/ */
use object::Object; use std::fmt;
use predicates::IsBool; use object::Obj;
use preds;
impl IsBool for Object { /// The Scheme boolean type. It can be `True` or `False`.
fn is_bool(&self) -> bool { pub enum Bool { True, False }
match *self {
Object::Bool(_) => true, impl Obj for Bool { }
_ => false,
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)] #[cfg(test)]
mod tests { mod tests {
use object::Object; use object::Object;

View file

@ -23,7 +23,8 @@ pub enum Obj {
} }
pub trait Object: pub trait Object:
fmt::Display fmt::Debug +
fmt::Display
{ {
fn as_any(&self) -> &Any; fn as_any(&self) -> &Any;
fn as_pair(&self) -> Option<&Pair>; fn as_pair(&self) -> Option<&Pair>;
@ -31,6 +32,10 @@ pub trait Object:
} }
impl Obj { 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> { pub fn unbox_as<T: 'static + Object>(&self) -> Option<&T> {
match self { match self {
Obj::Null => None, 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)] //#[derive(Debug, PartialEq)]
//pub enum Object { //pub enum Object {
// ByteVector(Vec<u8>), // ByteVector(Vec<u8>),

View file

@ -13,6 +13,10 @@ pub struct Pair {
} }
impl Pair { impl Pair {
pub fn empty() -> Pair {
Pair { car: Obj::Null, cdr: Obj::Null }
}
fn fmt_pair(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt_pair(&self, f: &mut fmt::Formatter) -> fmt::Result {
let r = write!(f, "{}", self.car); let r = write!(f, "{}", self.car);
r.and_then(|r| match self.cdr { r.and_then(|r| match self.cdr {
@ -39,3 +43,9 @@ impl fmt::Display for Pair {
.and_then(|_| write!(f, ")")) .and_then(|_| write!(f, ")"))
} }
} }
impl fmt::Debug for Pair {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}

View file

@ -9,6 +9,12 @@ use super::*;
pub struct Sym(String); pub struct Sym(String);
impl Sym {
pub fn new(value: String) -> Sym {
Sym(value)
}
}
impl Object for Sym { impl Object for Sym {
fn as_any(&self) -> &Any { self } fn as_any(&self) -> &Any { self }
fn as_pair(&self) -> Option<&Pair> { None } fn as_pair(&self) -> Option<&Pair> { None }
@ -20,3 +26,9 @@ impl fmt::Display for Sym {
write!(f, "{}", self.0) write!(f, "{}", self.0)
} }
} }
impl fmt::Debug for Sym {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}