[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,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<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