Skip to content

Commit

Permalink
Merge pull request #5 from KPMGE/refactor-parser
Browse files Browse the repository at this point in the history
Refactor parser
  • Loading branch information
KPMGE authored Mar 22, 2024
2 parents ce708ff + ceaa275 commit 63b8454
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 245 deletions.
22 changes: 4 additions & 18 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ use crate::token::Token;

#[derive(Debug, Eq, Clone, PartialEq)]
pub enum Expression {
Int {
token: Token, // Token::Int(val)
},
Identifier {
token: Token, // Token::Idetifier(name)
},
Int(i32),
Identifier(String),
Boolean(bool),
Prefix {
operator: Token, // Token::Bang, Token::Minus
right: Box<Expression>,
Expand All @@ -17,23 +14,16 @@ pub enum Expression {
left: Box<Expression>,
right: Box<Expression>,
},
Boolean {
token: Token, // Token::True or Token::False
value: bool,
},
IfExpression {
token: Token, // Token::If
condition: Box<AstNode>,
consequence: BlockStatement, // Statement::BlockStatement
alternative: Option<BlockStatement>, // Statement::BlockStatement
},
FunctionExpression {
token: Token, // Token::Fn
parameters: Vec<Token>, // Vec<Token::Identifier>
body: BlockStatement,
},
CallExpression {
token: Token, // Token::LeftParentesis
function: Box<Expression>, // Expression::FunctionExpression or Expression::Identifier
arguments: Vec<Expression>,
},
Expand All @@ -47,15 +37,11 @@ pub struct BlockStatement {

#[derive(Debug, Eq, Clone, PartialEq)]
pub enum Statement {
ReturnStatement(Expression),
LetStatement {
token: Token, // Token::Let
name: Expression, // Expression::Identifer
value: Expression,
},
ReturnStatement {
token: Token, // Token::Return
value: Expression,
},
}

#[derive(Debug, PartialEq, PartialOrd)]
Expand Down
216 changes: 111 additions & 105 deletions src/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,116 +30,122 @@ impl Evaluator {
pub fn eval(&mut self, node: AstNode) -> Object {
match node {
AstNode::Program { statements } => self.eval_program(statements),
AstNode::Statement(statement) => match statement {
Statement::ReturnStatement { value, .. } => {
let result_object = self.eval(AstNode::Expression(value));
Object::Return(Box::new(result_object))
AstNode::Statement(statement) => self.eval_statement(statement),
AstNode::Expression(expression) => self.eval_expression(expression),
}
}

fn eval_expression(&mut self, expression: Expression) -> Object {
match expression {
Expression::Int(value) => Object::Integer(value),
Expression::Boolean(value) => Object::Boolean(value),
Expression::Prefix { operator, right } => {
let right = self.eval(AstNode::Expression(*right));
self.eval_prefix_expression(operator, right)
}
Expression::Infix {
operator,
left,
right,
} => {
let left = self.eval(AstNode::Expression(*left));
let right = self.eval(AstNode::Expression(*right));
self.eval_infix_expression(left, right, operator)
}
Expression::IfExpression {
condition,
consequence,
alternative,
..
} => {
let condition = self.eval(*condition);

if condition.is_truthy() {
return self.eval_block_statement(consequence.statements);
}
Statement::LetStatement { name, value, .. } => {
let let_name = match name {
Expression::Identifier {
token: Token::Identifier(str),
} => str,
_ => panic!(),
};

let result_object = self.eval(AstNode::Expression(value));
self.context.insert(let_name.clone(), result_object.clone());
result_object

if let Some(alternative_block) = alternative {
return self.eval_block_statement(alternative_block.statements);
}

Object::Null
}
Expression::Identifier(let_name) => self
.context
.get(&let_name)
.expect("ERROR: Could not find identifer")
.clone(),
Expression::FunctionExpression {
parameters, body, ..
} => Object::Function {
parameters,
body,
scope: HashMap::new(),
},
AstNode::Expression(expression) => match expression {
Expression::Int {
token: Token::Int(value),
} => Object::Integer(value.parse::<i32>().expect("Could not parse integer")),
Expression::Boolean { value, .. } => Object::Boolean(value),
Expression::Prefix { operator, right } => {
let right = self.eval(AstNode::Expression(*right));
self.eval_prefix_expression(operator, right)
}
Expression::Infix {
operator,
left,
right,
} => {
let left = self.eval(AstNode::Expression(*left));
let right = self.eval(AstNode::Expression(*right));
self.eval_infix_expression(left, right, operator)
}
Expression::IfExpression {
condition,
consequence,
alternative,
..
} => {
let condition = self.eval(*condition);

if condition.is_truthy() {
return self.eval_block_statement(consequence.statements);
}

if let Some(alternative_block) = alternative {
return self.eval_block_statement(alternative_block.statements);
}

Object::Null
Expression::CallExpression {
function,
arguments,
..
} => {
let function = self.eval(AstNode::Expression(*function));

match function {
Object::Function {
parameters,
body,
mut scope,
} => self.eval_function_call(parameters, arguments, body, &mut scope),
obj => panic!("Wrong object, expected Object::Function, got: {:?}", obj),
}
Expression::Identifier {
token: Token::Identifier(let_name),
} => self
.context
.get(&let_name)
.expect("ERROR: Could not find identifer")
.clone(),
Expression::FunctionExpression {
parameters, body, ..
} => Object::Function {
parameters,
body,
scope: HashMap::new(),
},
Expression::CallExpression {
function,
arguments,
..
} => {
let function = self.eval(AstNode::Expression(*function));

match function {
Object::Function {
parameters,
body,
mut scope,
} => {
let previous_context = self.context.clone();

let arguments = self.eval_expressions(arguments);

// set the parameters in the given scope
parameters
.iter()
.enumerate()
.for_each(|(idx, param)| match param {
Token::Identifier(param_name) => {
scope.insert(
param_name.clone(),
arguments.get(idx).unwrap().clone(),
);
}
_ => panic!(),
});

self.context = scope;
let result = self.eval_block_statement(body.statements);
self.context = previous_context;

result
}
obj => panic!("Wrong object, expected Object::Function, got: {:?}", obj),
}
}
}
}

fn eval_function_call(
&mut self,
parameters: Vec<Token>,
arguments: Vec<Expression>,
body: BlockStatement,
scope: &mut HashMap<String, Object>,
) -> Object {
let previous_context = self.context.clone();

let arguments = self.eval_expressions(arguments);

// set the parameters in the given scope
parameters
.iter()
.enumerate()
.for_each(|(idx, param)| match param {
Token::Identifier(param_name) => {
scope.insert(param_name.clone(), arguments.get(idx).unwrap().clone());
}
_ => todo!(),
},
_ => panic!(),
});

self.context = scope.clone();
let result = self.eval_block_statement(body.statements);
self.context = previous_context;

result
}

fn eval_statement(&mut self, statement: Statement) -> Object {
match statement {
Statement::ReturnStatement(value) => {
let result_object = self.eval(AstNode::Expression(value));
Object::Return(Box::new(result_object))
}
Statement::LetStatement { name, value } => {
let let_name = match name {
Expression::Identifier(identifier_name) => identifier_name,
_ => panic!(),
};

let result_object = self.eval(AstNode::Expression(value));
self.context.insert(let_name.clone(), result_object.clone());
result_object
}
}
}

Expand Down
47 changes: 15 additions & 32 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,7 @@ impl Parser {
return None;
}

Some(AstNode::Statement(Statement::LetStatement {
token: Token::Let,
name,
value,
}))
Some(AstNode::Statement(Statement::LetStatement { name, value }))
}

fn parse_expression_statement(&mut self) -> Option<AstNode> {
Expand All @@ -119,10 +115,7 @@ impl Parser {

let expression = self.parse_expression(Precedence::Lowest)?;

Some(AstNode::Statement(Statement::ReturnStatement {
token: Token::Return,
value: expression,
}))
Some(AstNode::Statement(Statement::ReturnStatement(expression)))
}

fn parse_expression(&mut self, precedence: Precedence) -> Option<Expression> {
Expand Down Expand Up @@ -158,21 +151,22 @@ impl Parser {
}

fn parse_identifier(&mut self) -> Option<Expression> {
if let Token::Identifier(_) = &self.current_token {
let identifier = Expression::Identifier {
token: self.current_token.clone(),
};
return Some(identifier);
if let Token::Identifier(name) = &self.current_token {
return Some(Expression::Identifier(name.clone()));
}
None
}

fn parse_int(&mut self) -> Option<Expression> {
if let Token::Int(_) = &self.current_token {
let int_expression = Expression::Int {
token: self.current_token.clone(),
};
return Some(int_expression);
if let Token::Int(num_str) = &self.current_token {
let num = match num_str.parse::<i32>() {
Ok(num) => Some(num),
Err(_) => {
self.report_error(&format!("error parsing integer: {}", num_str));
None
}
}?;
return Some(Expression::Int(num));
}
None
}
Expand Down Expand Up @@ -225,10 +219,7 @@ impl Parser {
}
};

Some(Expression::Boolean {
token: self.current_token.clone(),
value,
})
Some(Expression::Boolean(value))
}

fn parse_if_expression(&mut self) -> Option<Expression> {
Expand Down Expand Up @@ -259,7 +250,6 @@ impl Parser {
};

Some(Expression::IfExpression {
token: Token::If,
condition: Box::new(AstNode::Expression(condition)),
consequence,
alternative,
Expand All @@ -277,11 +267,7 @@ impl Parser {
let parameters = self.parse_function_parameters()?;
let body = self.parse_block_statement()?;

Some(Expression::FunctionExpression {
token: Token::Function,
parameters,
body,
})
Some(Expression::FunctionExpression { parameters, body })
}

fn parse_function_parameters(&mut self) -> Option<Vec<Token>> {
Expand Down Expand Up @@ -347,13 +333,10 @@ impl Parser {
})
}
fn parse_call_expression(&mut self, function: Expression) -> Option<Expression> {
let token = self.current_token.clone();

self.advance_tokens();
let arguments = self.parse_call_expression_arguments()?;

Some(Expression::CallExpression {
token,
function: Box::new(function),
arguments,
})
Expand Down
Loading

0 comments on commit 63b8454

Please sign in to comment.