1
0
Fork 0
monkey-interpreter/src/parser/ast/mod.rs

713 lines
20 KiB
Rust

// TODO: Maybe implement String method to pretty print all AST nodes
use {
crate::{
lexer::{Token, TokenType},
parser::{Error as ParserError, Parser},
},
itertools::Itertools,
std::{
cmp::PartialOrd,
convert::From,
fmt::{Display, Formatter, Result as FmtResult},
},
};
#[derive(Debug, PartialEq)]
pub struct Program {
pub statements: Vec<Statement>,
}
impl Display for Program {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let mut out = String::new();
for statement in &self.statements {
out.push_str(&statement.to_string());
}
f.write_str(&out)
}
}
#[derive(Debug, PartialEq)]
pub enum Statement {
Let(LetStatement),
Return(ReturnStatement),
ExpressionStatement(ExpressionStatement),
BlockStatement(BlockStatement),
}
impl<'a> Statement {
pub fn parse(parser: &'a mut Parser, token: Token) -> Option<Self> {
match token.name {
TokenType::Let => Some(Statement::Let(LetStatement::parse(parser)?)),
TokenType::Return => Some(Statement::Return(ReturnStatement::parse(parser)?)),
_ => Some(Statement::ExpressionStatement(ExpressionStatement::parse(
parser, token,
)?)),
}
}
}
impl Display for Statement {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
match self {
Statement::Let(v) => f.write_str(&v.to_string()),
Statement::Return(v) => f.write_str(&v.to_string()),
Statement::ExpressionStatement(v) => f.write_str(&v.to_string()),
Statement::BlockStatement(v) => f.write_str(&v.to_string()),
}
}
}
#[derive(Debug, PartialEq)]
pub struct LetStatement {
// name field is to store the identifier of the binding
name: Identifier,
// value is to store the expression that'll produce value
value: Option<Expression>,
}
impl LetStatement {
pub fn new(name: Identifier) -> Self {
Self { name, value: None }
}
pub fn with_value(name: Identifier, value: Option<Expression>) -> Self {
Self { name, value }
}
// TODO: Implement code to parse let statement
pub fn parse(parser: &mut Parser) -> Option<Self> {
let mut stmt = LetStatement {
name: Identifier::new(TokenType::Let, "placeholder_value"),
value: None,
};
let ident = parser.expect_peek(TokenType::Ident)?;
stmt.name.value = ident.literal?;
parser.expect_peek(TokenType::Assign)?;
// TODO: Right now, We are just skipping over all the expressions
// That'll come later
// Also, Right now, It hangs forever in case there is no semicolon at the end
while parser.lexer.next() != Some(Token::new(TokenType::Semicolon)) {}
Some(stmt)
}
const fn token_literal() -> &'static str {
"let"
}
}
impl Display for LetStatement {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let mut out = format!("{} {} = ", Self::token_literal(), self.name.value);
if let Some(v) = &self.value {
let a: String = v.into();
out.push_str(&a);
}
out.push(';');
f.write_str(&out)
}
}
#[derive(Debug, PartialEq)]
pub struct ReturnStatement {
return_value: Option<Expression>,
}
impl ReturnStatement {
fn parse(parser: &mut Parser) -> Option<Self> {
let stmt = ReturnStatement {
return_value: Some(Expression::None),
};
while parser.lexer.next() != Some(Token::new(TokenType::Semicolon)) {}
return Some(stmt);
}
const fn token_literal() -> &'static str {
"return"
}
}
impl Display for ReturnStatement {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let mut out = String::from(Self::token_literal());
if let Some(v) = &self.return_value {
out.push(' ');
let a: String = v.into();
out.push_str(&a);
}
out.push(';');
f.write_str(&out)
}
}
#[derive(Debug, PartialEq)]
pub struct ExpressionStatement {
token: Token,
expression: Expression,
}
impl ExpressionStatement {
pub fn new(token: Token, expression: Expression) -> Self {
Self { token, expression }
}
fn parse(parser: &mut Parser, current_token: Token) -> Option<Self> {
let stmt = ExpressionStatement {
token: current_token.clone(),
expression: Expression::parse(parser, current_token, ExpressionPriority::Lowest)?,
};
if parser.peek_token_is(TokenType::Semicolon) {
parser.lexer.next();
}
Some(stmt)
}
}
impl Display for ExpressionStatement {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
f.write_str(&self.expression.to_string())
}
}
#[derive(Debug, PartialEq, Copy, PartialOrd, Clone)]
pub enum ExpressionPriority {
Lowest = 0,
Equals = 1,
LessGreater = 2,
Sum = 3,
Product = 4,
Prefix = 5,
Call = 6,
}
#[derive(Debug, PartialEq)]
pub enum Expression {
Identifier(Identifier),
IntegerLiteral(IntegerLiteral),
PrefixExpression(PrefixExpression),
InfixExpression(InfixExpression),
BooleanExpression(BooleanExpression),
IfExpression(IfExpression),
FunctionExpression(FunctionLiteral),
CallExpression(CallExpression),
// TODO: Temporary placeholder value. Should be removed once this section is done
None,
}
impl Expression {
fn parse(parser: &mut Parser, ctoken: Token, precedence: ExpressionPriority) -> Option<Self> {
match parser.prefix_parse_fns.get(&ctoken.name) {
Some(prefix) => {
let mut left_expr = prefix(parser, ctoken);
while !parser.peek_token_is(TokenType::Semicolon)
&& precedence < parser.peek_precedence()
{
let peek_token = match parser.lexer.peek() {
Some(token) => token.clone(),
None => return left_expr,
};
match parser.infix_parse_fns.get(&peek_token.name) {
Some(infix) => {
let next_token = parser.lexer.next()?;
left_expr = infix(parser, next_token, left_expr.unwrap());
}
None => return left_expr,
};
}
left_expr
}
None => {
parser.no_prefix_parse_fn_error(&ctoken.name);
None
}
}
}
pub fn parse_grouped_expression(parser: &mut Parser, _token: Token) -> Option<Self> {
let next_token = parser.lexer.next()?;
let expr = Expression::parse(parser, next_token, ExpressionPriority::Lowest);
if parser.expect_peek(TokenType::RParen).is_none() {
None
} else {
expr
}
}
}
impl Display for Expression {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let value = match self {
Expression::Identifier(v) => v.to_string(),
Expression::IntegerLiteral(v) => v.value.to_string(),
Expression::PrefixExpression(v) => v.to_string(),
Expression::InfixExpression(v) => v.to_string(),
Expression::BooleanExpression(v) => v.to_string(),
Expression::IfExpression(v) => v.to_string(),
Expression::FunctionExpression(v) => v.to_string(),
Expression::CallExpression(v) => v.to_string(),
Expression::None => "None".into(),
};
f.write_str(&value)
}
}
impl From<&Expression> for String {
fn from(expr: &Expression) -> String {
expr.to_string()
}
}
// Identifier will be an expression
// Identifier in a let statement like, let x = 5; where `x` is an identifier doesn't produce a value
// but an identifier *can* produce value when used on rhs, e.g. let x = y; Here `y` is producing a value
#[derive(Debug, PartialEq)]
pub struct Identifier {
token: TokenType,
value: String,
}
impl Identifier {
pub fn new(token: TokenType, v: &str) -> Self {
Identifier {
token: token,
value: v.to_string(),
}
}
pub fn parse(_parser: &mut Parser, token: Token) -> Option<Expression> {
Some(Expression::Identifier(Identifier::new(
token.name,
&token.literal?,
)))
}
}
impl Display for Identifier {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
f.write_str(&self.value)
}
}
#[derive(Debug, PartialEq)]
pub struct IntegerLiteral {
value: i64,
}
impl IntegerLiteral {
pub fn new(v: i64) -> Self {
Self { value: v }
}
pub fn parse(parser: &mut Parser, token: Token) -> Option<Expression> {
let n = match token.literal?.parse::<i64>() {
Ok(v) => v,
Err(e) => {
parser.errors.push(ParserError {
reason: e.to_string(),
});
return None;
}
};
Some(Expression::IntegerLiteral(IntegerLiteral::new(n)))
}
}
#[derive(Debug, PartialEq)]
pub struct PrefixExpression {
token: TokenType,
operator: String,
right: Box<Expression>,
}
impl PrefixExpression {
pub fn new(token: TokenType, operator: &str, right: Expression) -> Self {
Self {
token,
operator: operator.to_string(),
right: Box::new(right),
}
}
pub fn parse(parser: &mut Parser, ctoken: Token) -> Option<Expression> {
let next_token = parser.lexer.next()?;
let right_expr = Expression::parse(parser, next_token.clone(), ExpressionPriority::Prefix)?;
Some(Expression::PrefixExpression(PrefixExpression {
token: ctoken.name,
operator: ctoken.to_string().into(),
right: Box::new(right_expr),
}))
}
}
impl Display for PrefixExpression {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
f.write_fmt(format_args!(
"({}{})",
self.operator,
self.right.to_string()
))
}
}
#[derive(Debug, PartialEq)]
pub struct InfixExpression {
token: TokenType,
left: Box<Expression>,
operator: String,
right: Box<Expression>,
}
impl InfixExpression {
pub fn new(token: TokenType, left: Expression, operator: &str, right: Expression) -> Self {
Self {
token,
left: Box::new(left),
operator: operator.to_string(),
right: Box::new(right),
}
}
pub fn parse(parser: &mut Parser, token: Token, left_expr: Expression) -> Option<Expression> {
let cprecedence = parser.current_precedence(&token.name);
let next_token = parser.lexer.next()?;
let right_expr = Expression::parse(parser, next_token, cprecedence)?;
Some(Expression::InfixExpression(InfixExpression::new(
token.name,
left_expr,
&token.to_string(),
right_expr,
)))
}
}
impl Display for InfixExpression {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
f.write_fmt(format_args!(
"({} {} {})",
self.left.to_string(),
self.operator,
self.right.to_string(),
))
}
}
#[derive(Debug, PartialEq)]
pub struct BooleanExpression {
token: TokenType,
value: bool,
}
impl BooleanExpression {
pub fn new(token: TokenType) -> Self {
BooleanExpression {
token: token,
value: token == TokenType::True,
}
}
pub fn parse(_parser: &mut Parser, token: Token) -> Option<Expression> {
Some(Expression::BooleanExpression(BooleanExpression::new(
token.name,
)))
}
}
impl Display for BooleanExpression {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
f.write_str(&self.value.to_string())
}
}
#[derive(Debug, PartialEq)]
pub struct IfExpression {
condition: Box<Expression>,
consequence: BlockStatement,
alternative: Option<BlockStatement>,
}
impl IfExpression {
pub fn new(
condition: Expression,
consequence: BlockStatement,
alternative: Option<BlockStatement>,
) -> Self {
Self {
condition: Box::new(condition),
consequence,
alternative,
}
}
pub fn parse(parser: &mut Parser, _ctoken: Token) -> Option<Expression> {
if parser.expect_peek(TokenType::LParen).is_none() {
return None;
}
let next_token = parser.lexer.next()?;
let condition = Expression::parse(parser, next_token.clone(), ExpressionPriority::Lowest)?;
if parser.expect_peek(TokenType::RParen).is_none() {
return None;
}
if parser.expect_peek(TokenType::LBrace).is_none() {
return None;
}
let consequence = BlockStatement::parse(parser, next_token)?;
if parser.peek_token_is(TokenType::Else) {
let token = parser.lexer.next()?;
if parser.expect_peek(TokenType::LBrace).is_none() {
return None;
}
let alternative = BlockStatement::parse(parser, token);
Some(Expression::IfExpression(IfExpression::new(
condition,
consequence,
alternative,
)))
} else {
Some(Expression::IfExpression(IfExpression::new(
condition,
consequence,
None,
)))
}
}
}
impl Display for IfExpression {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let mut out = format!(
"if {} {{ {} }} ",
self.condition.to_string(),
self.consequence.to_string()
);
if let Some(alternative) = &self.alternative {
out += &format!("else {{ {} }}", alternative.to_string());
}
f.write_str(&out)
}
}
#[derive(Debug, PartialEq)]
pub struct BlockStatement {
statements: Vec<Statement>,
}
impl BlockStatement {
pub fn new(stmt: Vec<Statement>) -> Self {
Self { statements: stmt }
}
pub fn parse(parser: &mut Parser, _ogtoken: Token) -> Option<Self> {
let mut stmts = vec![];
let mut ctoken = parser.lexer.next();
while let Some(token) = ctoken {
if token.name == TokenType::RBrace {
break;
}
let stmt = Statement::parse(parser, token);
if stmt.is_some() {
stmts.push(stmt.unwrap());
}
ctoken = parser.lexer.next();
}
Some(BlockStatement::new(stmts))
}
}
impl Display for BlockStatement {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
let mut out = String::new();
for stmt in &self.statements {
out.push_str(&stmt.to_string());
}
f.write_str(&out)
}
}
#[derive(Debug, PartialEq)]
pub struct FunctionLiteral {
token: Token,
parameters: Vec<Identifier>,
body: BlockStatement,
}
impl FunctionLiteral {
pub fn new(token: Token, parameters: Vec<Identifier>, body: BlockStatement) -> Self {
Self {
token,
parameters,
body,
}
}
pub fn parse(parser: &mut Parser, ctoken: Token) -> Option<Expression> {
if parser.expect_peek(TokenType::LParen).is_none() {
return None;
}
let ntoken = parser.lexer.peek()?.clone();
let parameters = FunctionLiteral::parse_function_parameters(parser, ntoken)?;
if parser.expect_peek(TokenType::LBrace).is_none() {
return None;
}
let ntoken = parser.lexer.peek()?.clone();
let body = BlockStatement::parse(parser, ntoken)?;
Some(Expression::FunctionExpression(Self {
token: ctoken,
parameters,
body,
}))
}
fn parse_function_parameters(parser: &mut Parser, _ctoken: Token) -> Option<Vec<Identifier>> {
let mut out = vec![];
if parser.peek_token_is(TokenType::RParen) {
parser.lexer.next();
Some(out)
} else {
let ntoken = parser.lexer.next()?;
let ident = Identifier::new(ntoken.name, &ntoken.literal?);
out.push(ident);
while parser.peek_token_is(TokenType::Comma) {
parser.lexer.next();
let token = parser.lexer.next()?;
let ident = Identifier::new(token.name, &token.literal?);
out.push(ident);
}
if parser.expect_peek(TokenType::RParen).is_none() {
return None;
}
Some(out)
}
}
}
impl Display for FunctionLiteral {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
f.write_fmt(format_args!(
"{} {}({}) {}",
self.token.name.to_string(),
self.token.literal.as_ref().unwrap(),
self.parameters.iter().join(","),
""
))
}
}
#[derive(Debug, PartialEq)]
pub struct CallExpression {
function: Box<Expression>,
arguments: Vec<Expression>,
}
impl CallExpression {
pub fn new(f: Expression, arguments: Vec<Expression>) -> Self {
Self {
function: Box::new(f),
arguments,
}
}
pub fn parse(parser: &mut Parser, ctoken: Token, expr: Expression) -> Option<Expression> {
let args = Self::parse_call_arguments(parser, ctoken);
Some(Expression::CallExpression(Self {
function: Box::new(expr),
arguments: args?,
}))
}
fn parse_call_arguments(parser: &mut Parser, _ctoken: Token) -> Option<Vec<Expression>> {
let mut expressions = vec![];
if let Some(token) = parser.lexer.peek() {
if token.name == TokenType::RParen {
parser.lexer.next();
return Some(expressions);
}
}
let ntoken = match parser.lexer.next() {
Some(token) => token,
None => return Some(expressions),
};
Expression::parse(parser, ntoken, ExpressionPriority::Lowest).map(|e| expressions.push(e));
while parser.peek_token_is(TokenType::Comma) {
parser.lexer.next();
let token = match parser.lexer.next() {
Some(v) => v,
None => return Some(expressions),
};
Expression::parse(parser, token, ExpressionPriority::Lowest)
.map(|e| expressions.push(e));
}
if parser.expect_peek(TokenType::RParen).is_none() {
return None;
}
Some(expressions)
}
}
impl Display for CallExpression {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
f.write_fmt(format_args!(
"{}({})",
self.function,
self.arguments.iter().join(", ")
))
}
}
#[cfg(test)]
mod tests {
use crate::{
lexer::TokenType,
parser::{
ast::{Expression, Identifier, LetStatement, ReturnStatement, Statement},
Program,
},
};
#[test]
fn test_string() {
let program = Program {
statements: vec![
Statement::Let(LetStatement {
name: Identifier::new(TokenType::Ident, "myVar"),
value: Some(Expression::Identifier(Identifier::new(
TokenType::Ident,
"anotherVar",
))),
}),
Statement::Return(ReturnStatement {
return_value: Some(Expression::Identifier(Identifier::new(
TokenType::Int,
"5",
))),
}),
Statement::Return(ReturnStatement { return_value: None }),
],
};
assert_eq!(
program.to_string(),
"let myVar = anotherVar;return 5;return;"
);
}
}