Refactored parser back to using traits rather than enum, Added gitignore, Added return statement

This commit is contained in:
Ishan Jain 2019-09-09 00:44:27 +05:30
parent 98023fe219
commit 68330a8156
5 changed files with 130 additions and 61 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
target/ target/
.vscode/settings.json
.vscode/launch.json

View File

@ -1,52 +1,68 @@
use crate::lexer::Token; use crate::{
use crate::parser::{ParseError, Parser}; lexer::Token,
parser::{ParseError, Parser},
};
use std::any::Any;
use std::error::Error; use std::error::Error;
pub enum Node { pub trait Node {
Statement(StatementType), fn string(&self) -> String
Expression, where
Self: Sized + Any;
} }
#[derive(PartialEq, Debug)] pub trait Statement: Node {
pub enum StatementType { fn parse(&mut Parser) -> Result<Self, ParseError>
Let(LetStatement), where
Ident(Identifier), Self: Sized + Any;
}
pub trait Expression: Node {
fn parse(&mut Parser) -> Result<Self, Box<dyn Error>>
where
Self: Sized + Any;
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct LetStatement { pub struct Let {
name: Identifier, name: Identifier,
// value: dyn Expression, // value: dyn Expression,
} }
impl LetStatement { impl Let {
#[allow(dead_code)] #[allow(dead_code)]
pub fn new(identifier: Identifier) -> StatementType { pub fn new(identifier: Identifier) -> Let {
StatementType::Let(LetStatement { name: identifier }) Let { name: identifier }
}
} }
pub fn parse(parser: &mut Parser) -> Result<LetStatement, Box<dyn Error>> { impl Node for Let {
fn string(&self) -> String {
String::new() // TODO: Complete how I want to format strings
}
}
impl Statement for Let {
fn parse(parser: &mut Parser) -> Result<Let, ParseError> {
let name; let name;
//TODO: Add expression parser //TODO: Add expression parser
match parser.lexer.next() { match parser.lexer.next() {
Some(v) => match v { Some(v) => match v {
Token::Ident(q) => name = Identifier { name: q }, Token::Ident(q) => name = Identifier { name: q },
n @ _ => { n @ _ => {
return Err(Box::new(ParseError::new(&format!( return Err(ParseError::new(&format!("expected IDENT, Found {:?}", n)));
"expected IDENT, Found {:?}",
n
))))
} }
}, },
None => { None => {
return Err(Box::new(ParseError::new( return Err(ParseError::new(
"expected IDENT after let, Could not find it", "expected IDENT after let, Could not find it",
))) ))
} }
}; };
if !parser.expect_peek(Token::Assign) { if !parser.expect_peek(Token::Assign) {
return Err(Box::new(ParseError::new("expected =, Could not find it"))); return Err(ParseError::new("expected =, Could not find it"));
} }
// TODO: Replace this with code to parse expressions correctly // TODO: Replace this with code to parse expressions correctly
@ -54,7 +70,37 @@ impl LetStatement {
parser.current_token = parser.lexer.next(); parser.current_token = parser.lexer.next();
} }
Ok(LetStatement { name }) Ok(Let { name })
}
}
#[derive(Debug, PartialEq)]
pub struct Return {
return_value: Expr,
}
impl Return {
pub fn new() -> Return {
Return { return_value: Expr }
}
}
#[derive(Debug, PartialEq)]
pub struct Expr; // TODO: Replace with actual expressions parser
impl Node for Return {
fn string(&self) -> String {
String::new() // TODO: Complete how I want to format return statements
}
}
impl Statement for Return {
fn parse(parser: &mut Parser) -> Result<Return, ParseError> {
while !parser.current_token_is(Token::Semicolon) {
parser.current_token = parser.lexer.next();
}
Ok(Return { return_value: Expr })
} }
} }

View File

@ -3,7 +3,7 @@ mod program;
pub use self::program::Program; pub use self::program::Program;
use self::ast::{LetStatement, StatementType}; use self::ast::{Let, Return, Statement};
use crate::lexer::{Lexer, Token}; use crate::lexer::{Lexer, Token};
use std::iter::Peekable; use std::iter::Peekable;
@ -19,28 +19,31 @@ impl<'a> Parser<'a> {
current_token: None, current_token: None,
} }
} }
fn parse_statement(&mut self, token: Token) -> Option<ast::StatementType> { fn parse_statement(&mut self, token: Token) -> Result<Box<dyn ast::Statement>, ParseError> {
match token { match token {
Token::Let => { Token::Let => match Let::parse(self) {
match LetStatement::parse(self) { Ok(v) => Ok(Box::new(v)),
Ok(v) => Some(StatementType::Let(v)), Err(e) => Err(e), //TODO: Return appropriate error
Err(_) => None, //TODO: Return appropriate error },
Token::Return => match Return::parse(self) {
Ok(v) => Ok(Box::new(v)),
Err(e) => Err(e),
},
n @ _ => {
println!("{:?}", n);
unimplemented!();
} }
} }
_ => None,
}
} }
fn expect_peek(&mut self, token: Token) -> bool { fn expect_peek(&mut self, token: Token) -> bool {
if let Some(v) = self.lexer.peek() { match self.lexer.peek() {
if v == &token { Some(v) if v == &token => {
self.current_token = self.lexer.next(); self.current_token = self.lexer.next();
true true
} else {
false
} }
} else { Some(v) => false,
false None => false,
} }
} }

View File

@ -1,10 +1,8 @@
use crate::lexer::{Lexer, Token}; use crate::lexer::{Lexer, Token};
use crate::parser::ast::StatementType; use crate::parser::{ast::Statement, Parser};
use crate::parser::Parser;
#[derive(Debug)]
pub struct Program { pub struct Program {
statements: Vec<StatementType>, statements: Vec<Box<dyn Statement>>,
} }
impl Program { impl Program {
@ -13,20 +11,22 @@ impl Program {
let mut parser = Parser::new(lexer); let mut parser = Parser::new(lexer);
loop { loop {
if let Some(token) = parser.lexer.next() { if let Some(token) = parser.lexer.next() {
parser.current_token = Some(token.clone());
if parser.current_token_is(Token::EOF) { if parser.current_token_is(Token::EOF) {
break; break;
} }
if let Some(stmt) = parser.parse_statement(token) { match parser.parse_statement(token) {
statements.push(stmt); Ok(v) => statements.push(v),
} else { Err(e) => {
println!("{:?}", e);
continue; continue;
} }
};
} else { } else {
break; break;
} }
} }
println!("statements={:?}", statements);
Program { statements } Program { statements }
} }
} }
@ -34,8 +34,9 @@ impl Program {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::lexer::Lexer; use crate::lexer::Lexer;
use crate::parser::ast::{Identifier, LetStatement}; use crate::parser::ast::{Identifier, Let, Statement};
use crate::parser::Program; use crate::parser::Program;
use std::any::Any;
#[test] #[test]
fn let_statements() { fn let_statements() {
let ip = " let ip = "
@ -43,22 +44,39 @@ mod tests {
let qq = 10; let qq = 10;
let foobar = 8388383; let foobar = 8388383;
"; ";
let out = Program {
statements: vec![ let expected_out = vec![
LetStatement::new(Identifier::new("yr")), Box::new(Let::new(Identifier::new("yr"))),
LetStatement::new(Identifier::new("qq")), Box::new(Let::new(Identifier::new("qq"))),
LetStatement::new(Identifier::new("foobar")), Box::new(Let::new(Identifier::new("foobar"))),
], ];
};
let lexer = Lexer::new(ip); let lexer = Lexer::new(ip);
let ast_tree = Program::parse(lexer); let as_tree = Program::parse(lexer);
if ast_tree.statements.len() != 3 { assert_eq!(as_tree.statements.len(), 3);
assert_eq!(ast_tree.statements.len(), 3);
for (out, expected_out) in as_tree.statements.into_iter().zip(expected_out.into_iter()) {
let out: Option<Let> =
if std::any::TypeId::of::<Let>() == std::any::TypeId::of::<dyn Statement>() {
Some(unsafe { std::mem::transmute::<Box<dyn Statement>, Let>(out) })
} else {
None
};
if Box::new(out.unwrap()) == expected_out {}
}
} }
for (out, expected_out) in ast_tree.statements.iter().zip(out.statements.iter()) { #[test]
assert_eq!(out, expected_out); fn return_statements() {
} let ip = "
return 5;
return 10;
return 80932;
";
let lexer = Lexer::new(ip);
let as_tree = Program::parse(lexer);
assert_eq!(as_tree.statements.len(), 3);
} }
} }