From 142b34edc40f97624c61b4a37a0d1b77ea084edc Mon Sep 17 00:00:00 2001 From: ishanjain28 Date: Sat, 7 Sep 2019 01:16:52 +0530 Subject: [PATCH] Refactored again, Compiles now. --- Cargo.lock | 6 ++-- Cargo.toml | 3 +- src/parser/ast/mod.rs | 45 ++++++++++++++++++------- src/parser/mod.rs | 76 +++++++++++++++++++------------------------ src/parser/program.rs | 61 ++++++++++++++++++++++++++++++++++ src/repl.rs | 2 +- 6 files changed, 134 insertions(+), 59 deletions(-) create mode 100644 src/parser/program.rs diff --git a/Cargo.lock b/Cargo.lock index 41d5784..6d50657 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,13 +4,13 @@ name = "interpreter" version = "0.1.0" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" diff --git a/Cargo.toml b/Cargo.toml index 733bfdb..60ef0aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" authors = ["ishanjain28 "] [dependencies] -lazy_static = "1.2.0" +lazy_static = "1.4.0" + diff --git a/src/parser/ast/mod.rs b/src/parser/ast/mod.rs index a3b1edf..83915a9 100644 --- a/src/parser/ast/mod.rs +++ b/src/parser/ast/mod.rs @@ -1,41 +1,62 @@ +use super::ParserError; use crate::lexer::Lexer; +use std::error::Error; pub trait Node { - fn token_literal(&self) -> String; + fn token_literal(&self) -> &'static str; + fn validate(&self) -> Result<(), Box>; } + pub trait Statement: Node { - fn parse(&self, &mut Lexer) -> Box; + fn parse(&mut Lexer) -> Self + where + Self: Sized; } pub trait Expression: Node {} -pub struct Let { +#[derive(Debug)] +pub struct LetStatement { name: Identifier, // value: dyn Expression, } -impl Node for Let { - fn token_literal(&self) -> String { - "let".to_owned() +impl Node for LetStatement { + fn validate(&self) -> Result<(), Box> { + if self.token_literal() != "let" { + return Err(Box::new(ParserError::new( + "self.token_literal is not set, got=".to_owned() + self.token_literal(), + ))); + } + Ok(()) + } + + fn token_literal(&self) -> &'static str { + "let" } } -impl Statement for Let { - fn parse(&self, lexer: &mut Lexer) -> Vec { - vec![Let { +impl Statement for LetStatement { + fn parse(lexer: &mut Lexer) -> LetStatement { + LetStatement { name: Identifier { name: "potato" }, // value: "", - }] + } } } +#[derive(Debug)] pub struct Identifier { name: &'static str, } impl Node for Identifier { - fn token_literal(&self) -> String { - "IDENT".to_owned() + fn validate(&self) -> Result<(), Box> { + Ok(()) + } + fn token_literal(&self) -> &'static str { + "IDENT" } } + impl Expression for Identifier {} diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 1e997e9..684d59b 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,49 +1,41 @@ -mod ast; +pub mod ast; +mod program; -use self::ast::{Let, Statement}; -use super::lexer::Lexer; +pub use self::program::Program; -pub struct Program { - statements: Vec>, -} +use self::ast::{LetStatement, Statement}; +use crate::lexer::{Lexer, Token}; -impl Program { - pub fn token_literal(&self) -> String { - if self.statements.len() > 0 { - self.statements[0].token_literal() - } else { - "".to_owned() - } - } +struct Parser {} - pub fn parse(lexer: Lexer) -> Program { - let mut statements = vec![]; - - Program { statements } - } -} - -#[cfg(test)] -mod tests { - use crate::lexer::Lexer; - use crate::parser::Program; - - #[test] - fn let_statements() { - let ip = " - let yr = 5; - let qq = 10; - let foobar = 8388383; - "; - - let lexer = Lexer::new(ip); - let ast_tree = Program::parse(lexer); - - if ast_tree.statements.len() != 3 { - eprintln!( - "statements length not equal to 3. got {}", - ast_tree.statements - ); +impl Parser { + fn parse_statement(token: Token, lexer: &mut Lexer) -> Option> { + match token { + Token::Let => Some(Box::new(LetStatement::parse(lexer))), + _ => unimplemented!(), } } } + +#[derive(Debug)] +struct ParserError { + desc: String, +} + +impl std::fmt::Display for ParserError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "ParserError: ") + } +} + +impl std::error::Error for ParserError { + fn description(&self) -> &str { + &self.desc + } +} + +impl ParserError { + fn new(desc: String) -> ParserError { + ParserError { desc } + } +} diff --git a/src/parser/program.rs b/src/parser/program.rs new file mode 100644 index 0000000..6414612 --- /dev/null +++ b/src/parser/program.rs @@ -0,0 +1,61 @@ +use crate::lexer::{Lexer, Token}; +use crate::parser::ast::{LetStatement, Statement}; +use crate::parser::Parser; + +pub struct Program { + statements: Vec>, +} + +impl Program { + pub fn token_literal(&self) -> &'static str { + if self.statements.len() > 0 { + self.statements[0].token_literal() + } else { + "" + } + } + + pub fn parse(mut lexer: Lexer) -> Program { + let mut statements = vec![]; + + loop { + if let Some(token) = lexer.next() { + if token == Token::EOF { + break; + } + + if let Some(stmt) = Parser::parse_statement(token, &mut lexer) { + statements.push(stmt); + } else { + continue; + } + } else { + break; + } + } + + Program { statements } + } +} + +#[cfg(test)] +mod tests { + use crate::lexer::Lexer; + use crate::parser::Program; + + #[test] + fn let_statements() { + let ip = " + let yr = 5; + let qq = 10; + let foobar = 8388383; + "; + + let lexer = Lexer::new(ip); + let ast_tree = Program::parse(lexer); + + if ast_tree.statements.len() != 3 { + assert_eq!(ast_tree.statements.len(), 3); + } + } +} diff --git a/src/repl.rs b/src/repl.rs index ba4306a..ee7a1f1 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -14,7 +14,7 @@ pub fn init() { fn start(mut ip: R, mut out: W) { loop { - out.write_fmt(format_args!("{}", PROMPT)).unwrap(); + out.write(PROMPT.as_bytes()).unwrap(); out.flush().unwrap(); let mut s = String::new(); ip.read_line(&mut s).unwrap();