Refactored again, Compiles now.

This commit is contained in:
Ishan Jain 2019-09-07 01:16:52 +05:30
parent f202d0dacd
commit 142b34edc4
6 changed files with 134 additions and 59 deletions

6
Cargo.lock generated
View File

@ -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"

View File

@ -4,4 +4,5 @@ version = "0.1.0"
authors = ["ishanjain28 <ishanjain28@gmail.com>"]
[dependencies]
lazy_static = "1.2.0"
lazy_static = "1.4.0"

View File

@ -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<dyn Error>>;
}
pub trait Statement: Node {
fn parse(&self, &mut Lexer) -> Box<dyn Statement>;
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<dyn Error>> {
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<dyn Statement> {
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<dyn Error>> {
Ok(())
}
fn token_literal(&self) -> &'static str {
"IDENT"
}
}
impl Expression for Identifier {}

View File

@ -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<Box<dyn Statement>>,
}
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<Box<dyn ast::Statement>> {
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 }
}
}

61
src/parser/program.rs Normal file
View File

@ -0,0 +1,61 @@
use crate::lexer::{Lexer, Token};
use crate::parser::ast::{LetStatement, Statement};
use crate::parser::Parser;
pub struct Program {
statements: Vec<Box<dyn Statement>>,
}
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);
}
}
}

View File

@ -14,7 +14,7 @@ pub fn init() {
fn start<R: BufRead, W: Write>(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();