Back to using enum in AST

This commit is contained in:
Ishan Jain 2019-09-09 15:04:59 +05:30
parent 68330a8156
commit 77ecd6e3dd
3 changed files with 24 additions and 56 deletions

View File

@ -2,27 +2,19 @@ use crate::{
lexer::Token, lexer::Token,
parser::{ParseError, Parser}, parser::{ParseError, Parser},
}; };
use std::any::Any;
use std::error::Error;
pub trait Node { #[derive(Debug, PartialEq)]
fn string(&self) -> String pub enum Statement {
where Let(Let),
Self: Sized + Any;
Return(Return),
//ExpressionStatement(ExpressionStatement),
} }
pub trait Statement: Node { #[derive(Debug, PartialEq)]
fn parse(&mut Parser) -> Result<Self, ParseError> pub enum Expression {
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 Let { pub struct Let {
name: Identifier, name: Identifier,
@ -34,16 +26,8 @@ impl Let {
pub fn new(identifier: Identifier) -> Let { pub fn new(identifier: Identifier) -> Let {
Let { name: identifier } Let { name: identifier }
} }
}
impl Node for Let { pub fn parse(parser: &mut Parser) -> Result<Let, ParseError> {
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
@ -74,6 +58,9 @@ impl Statement for Let {
} }
} }
#[derive(Debug, PartialEq)]
pub struct Expr;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Return { pub struct Return {
return_value: Expr, return_value: Expr,
@ -83,19 +70,8 @@ impl Return {
pub fn new() -> Return { pub fn new() -> Return {
Return { return_value: Expr } Return { return_value: Expr }
} }
}
#[derive(Debug, PartialEq)] pub fn parse(parser: &mut Parser) -> Result<Return, ParseError> {
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) { while !parser.current_token_is(Token::Semicolon) {
parser.current_token = parser.lexer.next(); parser.current_token = parser.lexer.next();
} }

View File

@ -19,14 +19,14 @@ impl<'a> Parser<'a> {
current_token: None, current_token: None,
} }
} }
fn parse_statement(&mut self, token: Token) -> Result<Box<dyn ast::Statement>, ParseError> { fn parse_statement(&mut self, token: Token) -> Result<Statement, ParseError> {
match token { match token {
Token::Let => match Let::parse(self) { Token::Let => match Let::parse(self) {
Ok(v) => Ok(Box::new(v)), Ok(v) => Ok(Statement::Let(v)),
Err(e) => Err(e), //TODO: Return appropriate error Err(e) => Err(e), //TODO: Return appropriate error
}, },
Token::Return => match Return::parse(self) { Token::Return => match Return::parse(self) {
Ok(v) => Ok(Box::new(v)), Ok(v) => Ok(Statement::Return(v)),
Err(e) => Err(e), Err(e) => Err(e),
}, },
n @ _ => { n @ _ => {
@ -42,8 +42,7 @@ impl<'a> Parser<'a> {
self.current_token = self.lexer.next(); self.current_token = self.lexer.next();
true true
} }
Some(v) => false, Some(_) | None => false,
None => false,
} }
} }

View File

@ -2,7 +2,7 @@ use crate::lexer::{Lexer, Token};
use crate::parser::{ast::Statement, Parser}; use crate::parser::{ast::Statement, Parser};
pub struct Program { pub struct Program {
statements: Vec<Box<dyn Statement>>, statements: Vec<Statement>,
} }
impl Program { impl Program {
@ -36,7 +36,7 @@ mod tests {
use crate::lexer::Lexer; use crate::lexer::Lexer;
use crate::parser::ast::{Identifier, Let, Statement}; 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 = "
@ -46,9 +46,9 @@ mod tests {
"; ";
let expected_out = vec![ let expected_out = vec![
Box::new(Let::new(Identifier::new("yr"))), Statement::Let(Let::new(Identifier::new("yr"))),
Box::new(Let::new(Identifier::new("qq"))), Statement::Let(Let::new(Identifier::new("qq"))),
Box::new(Let::new(Identifier::new("foobar"))), Statement::Let(Let::new(Identifier::new("foobar"))),
]; ];
let lexer = Lexer::new(ip); let lexer = Lexer::new(ip);
let as_tree = Program::parse(lexer); let as_tree = Program::parse(lexer);
@ -56,14 +56,7 @@ mod tests {
assert_eq!(as_tree.statements.len(), 3); assert_eq!(as_tree.statements.len(), 3);
for (out, expected_out) in as_tree.statements.into_iter().zip(expected_out.into_iter()) { for (out, expected_out) in as_tree.statements.into_iter().zip(expected_out.into_iter()) {
let out: Option<Let> = assert_eq!(out, expected_out);
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 {}
} }
} }