Refactored again, Compiles now.
This commit is contained in:
parent
f202d0dacd
commit
142b34edc4
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -4,13 +4,13 @@
|
||||||
name = "interpreter"
|
name = "interpreter"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.2.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[metadata]
|
[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"
|
||||||
|
|
|
@ -4,4 +4,5 @@ version = "0.1.0"
|
||||||
authors = ["ishanjain28 <ishanjain28@gmail.com>"]
|
authors = ["ishanjain28 <ishanjain28@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = "1.2.0"
|
lazy_static = "1.4.0"
|
||||||
|
|
||||||
|
|
|
@ -1,41 +1,62 @@
|
||||||
|
use super::ParserError;
|
||||||
use crate::lexer::Lexer;
|
use crate::lexer::Lexer;
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
pub trait Node {
|
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 {
|
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 trait Expression: Node {}
|
||||||
|
|
||||||
pub struct Let {
|
#[derive(Debug)]
|
||||||
|
pub struct LetStatement {
|
||||||
name: Identifier,
|
name: Identifier,
|
||||||
// value: dyn Expression,
|
// value: dyn Expression,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for Let {
|
impl Node for LetStatement {
|
||||||
fn token_literal(&self) -> String {
|
fn validate(&self) -> Result<(), Box<dyn Error>> {
|
||||||
"let".to_owned()
|
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 {
|
impl Statement for LetStatement {
|
||||||
fn parse(&self, lexer: &mut Lexer) -> Vec<dyn Statement> {
|
fn parse(lexer: &mut Lexer) -> LetStatement {
|
||||||
vec![Let {
|
LetStatement {
|
||||||
name: Identifier { name: "potato" },
|
name: Identifier { name: "potato" },
|
||||||
// value: "",
|
// value: "",
|
||||||
}]
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Identifier {
|
pub struct Identifier {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for Identifier {
|
impl Node for Identifier {
|
||||||
fn token_literal(&self) -> String {
|
fn validate(&self) -> Result<(), Box<dyn Error>> {
|
||||||
"IDENT".to_owned()
|
Ok(())
|
||||||
|
}
|
||||||
|
fn token_literal(&self) -> &'static str {
|
||||||
|
"IDENT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression for Identifier {}
|
impl Expression for Identifier {}
|
||||||
|
|
|
@ -1,49 +1,41 @@
|
||||||
mod ast;
|
pub mod ast;
|
||||||
|
mod program;
|
||||||
|
|
||||||
use self::ast::{Let, Statement};
|
pub use self::program::Program;
|
||||||
use super::lexer::Lexer;
|
|
||||||
|
|
||||||
pub struct Program {
|
use self::ast::{LetStatement, Statement};
|
||||||
statements: Vec<Box<dyn Statement>>,
|
use crate::lexer::{Lexer, Token};
|
||||||
}
|
|
||||||
|
|
||||||
impl Program {
|
struct Parser {}
|
||||||
pub fn token_literal(&self) -> String {
|
|
||||||
if self.statements.len() > 0 {
|
|
||||||
self.statements[0].token_literal()
|
|
||||||
} else {
|
|
||||||
"".to_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse(lexer: Lexer) -> Program {
|
impl Parser {
|
||||||
let mut statements = vec![];
|
fn parse_statement(token: Token, lexer: &mut Lexer) -> Option<Box<dyn ast::Statement>> {
|
||||||
|
match token {
|
||||||
Program { statements }
|
Token::Let => Some(Box::new(LetStatement::parse(lexer))),
|
||||||
}
|
_ => unimplemented!(),
|
||||||
}
|
|
||||||
|
|
||||||
#[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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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
61
src/parser/program.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ pub fn init() {
|
||||||
|
|
||||||
fn start<R: BufRead, W: Write>(mut ip: R, mut out: W) {
|
fn start<R: BufRead, W: Write>(mut ip: R, mut out: W) {
|
||||||
loop {
|
loop {
|
||||||
out.write_fmt(format_args!("{}", PROMPT)).unwrap();
|
out.write(PROMPT.as_bytes()).unwrap();
|
||||||
out.flush().unwrap();
|
out.flush().unwrap();
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
ip.read_line(&mut s).unwrap();
|
ip.read_line(&mut s).unwrap();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user