Back to using enum in AST
This commit is contained in:
parent
68330a8156
commit
77ecd6e3dd
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user