diff options
Diffstat (limited to 'sloth/src/parser')
| -rw-r--r-- | sloth/src/parser/ast.rs | 27 | ||||
| -rw-r--r-- | sloth/src/parser/graph.rs | 197 | ||||
| -rw-r--r-- | sloth/src/parser/mod.rs | 4 | ||||
| -rw-r--r-- | sloth/src/parser/stmt.rs | 57 |
4 files changed, 197 insertions, 88 deletions
diff --git a/sloth/src/parser/ast.rs b/sloth/src/parser/ast.rs index 2c70156..749271c 100644 --- a/sloth/src/parser/ast.rs +++ b/sloth/src/parser/ast.rs @@ -1,3 +1,5 @@ +use std::fmt::{format, Display}; + use crate::lexer::{self, TokenType}; use crate::parser::ParsingError; @@ -49,16 +51,16 @@ impl Stmt { // TODO: Values & Constants #[derive(PartialEq, Clone, Debug)] pub enum StmtKind { - Block(Vec<StmtKind>), + Block(Vec<Stmt>), ExprStmt(Expr), IfStmt { condition: Expr, - if_then: Box<StmtKind>, - else_then: Option<Box<StmtKind>>, + if_then: Box<Stmt>, + else_then: Option<Box<Stmt>>, }, WhileStmt { condition: Expr, - body: Box<StmtKind>, + body: Box<Stmt>, }, DefineVariable { identifier: String, @@ -76,7 +78,7 @@ pub enum StmtKind { identifier: String, inputs: Vec<FunctionInput>, output: Option<String>, - body: Box<StmtKind>, + body: Box<Stmt>, }, Return(Expr), } @@ -117,6 +119,21 @@ impl From<Literal> for ExprKind { } } +impl Display for Literal { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let value = match self { + Literal::Integer(i) => format!("{i}"), + Literal::Float(f) => format!("{f}"), + Literal::Boolean(b) => format!("{b}"), + Literal::Character(c) => format!("'{c}'"), + Literal::String(s) => format!("\"{s}\""), + Literal::Array(a) => format!("<Array>"), + }; + + write!(f, "{value}") + } +} + #[derive(Debug, Clone, Copy, PartialEq)] pub enum BinaryOp { Add, diff --git a/sloth/src/parser/graph.rs b/sloth/src/parser/graph.rs index b2a9324..e8236be 100644 --- a/sloth/src/parser/graph.rs +++ b/sloth/src/parser/graph.rs @@ -1,16 +1,14 @@ use std::fmt::{Error, Write}; -use super::ast::{ExprKind, StmtKind}; +use super::ast::{Expr, ExprKind, Stmt, StmtKind}; pub struct GraphBuilder { - i: i32, graph: String, } impl GraphBuilder { - pub fn generate(ast: &[StmtKind]) -> Result<String, Error> { + pub fn generate(ast: &[Stmt]) -> Result<String, Error> { let mut this = Self { - i: 0, graph: String::new(), }; @@ -18,7 +16,6 @@ impl GraphBuilder { for stmt in ast.iter() { this.traverse_stmt0(stmt)?; } - this.i = 0; for stmt in ast.iter() { this.traverse_stmt(stmt)?; } @@ -27,12 +24,10 @@ impl GraphBuilder { Ok(this.graph) } - fn traverse_stmt0(&mut self, stmt: &StmtKind) -> Result<(), Error> { - self.i += 1; - - match stmt { + fn traverse_stmt0(&mut self, stmt: &Stmt) -> Result<(), Error> { + match &stmt.kind { StmtKind::Block(body) => { - writeln!(&mut self.graph, "N{} [shape=box label=\"Block\"];", self.i)?; + writeln!(&mut self.graph, "N{} [shape=box label=\"Block\"];", stmt.id)?; for stmt in body.iter() { self.traverse_stmt0(stmt)?; } @@ -41,17 +36,21 @@ impl GraphBuilder { writeln!( &mut self.graph, "N{} [shape=box label=\"ExprStmt\"];", - self.i + stmt.id, )?; - // self.traverse_expr0(expr); + self.traverse_expr0(expr)?; } StmtKind::IfStmt { condition, if_then, else_then, } => { - writeln!(&mut self.graph, "N{} [shape=box label=\"IfStmt\"];", self.i)?; - // self.traverse_expr0(condition); + writeln!( + &mut self.graph, + "N{} [shape=box label=\"IfStmt\"];", + stmt.id + )?; + self.traverse_expr0(condition)?; self.traverse_stmt0(if_then)?; if let Some(else_then) = else_then { self.traverse_stmt0(else_then)?; @@ -61,9 +60,9 @@ impl GraphBuilder { writeln!( &mut self.graph, "N{} [shape=box label=\"WhileStmt\"];", - self.i + stmt.id )?; - // self.traverse_expr0(condition); + self.traverse_expr0(condition)?; self.traverse_stmt0(body)?; } StmtKind::DefineVariable { @@ -74,17 +73,17 @@ impl GraphBuilder { writeln!( &mut self.graph, "N{} [shape=box label=\"DefineVariable\\n\\nIdentifier={}\\nType={}\"];", - self.i, identifier, typ + stmt.id, identifier, typ )?; - // self.traverse_expr0(value); + self.traverse_expr0(value)?; } StmtKind::AssignVariable { identifier, value } => { writeln!( &mut self.graph, "N{} [shape=box label=\"AssignVariable\\n\\nIdentifier={}\"];", - self.i, identifier + stmt.id, identifier )?; - // self.traverse_expr0(value); + self.traverse_expr0(value)?; } StmtKind::DefineFunction { identifier, @@ -96,7 +95,7 @@ impl GraphBuilder { &mut self.graph, "N{} [shape=box \ label=\"DefineFunction\\n\\nIdentifier={}\\nInputs={}\\nOutput={}\"];", - self.i, + stmt.id, identifier, inputs.len(), output.is_some() @@ -104,57 +103,137 @@ impl GraphBuilder { self.traverse_stmt0(body)?; } StmtKind::Return(expr) => { - writeln!(&mut self.graph, "N{} [shape=box label=\"Return\"];", self.i)?; - // self.traverse_expr0(expr); + writeln!( + &mut self.graph, + "N{} [shape=box label=\"Return\"];", + stmt.id + )?; + self.traverse_expr0(expr)?; } } Ok(()) } - fn traverse_expr0(&mut self, expr: &ExprKind) { - self.i += 1; - // match expr { - // Expr::Grouping(_) => todo!(), - // Expr::Literal(_) => todo!(), - // Expr::Identifier(_) => todo!(), - // Expr::BinaryOp { op, lhs, rhs } => todo!(), - // Expr::UnaryOp { op, value } => todo!(), - // Expr::Call { callee, args } => todo!(), - // } - } + fn traverse_expr0(&mut self, expr: &Expr) -> Result<(), Error> { + match &expr.kind { + ExprKind::Grouping(child) => { + writeln!( + &mut self.graph, + "N{} [shape=diamond label=\"Grouping\"];", + expr.id + )?; + self.traverse_expr0(child)?; + } + ExprKind::Literal(literal) => { + writeln!( + &mut self.graph, + "N{} [shape=diamond label=\"Literal\\n\\nValue={}\"];", + expr.id, literal + )?; + } + ExprKind::Identifier(identifier) => { + writeln!( + &mut self.graph, + "N{} [shape=diamond label=\"Identifier\\n\\nIdentifier={}\"];", + expr.id, identifier + )?; + } + ExprKind::BinaryOp { op, lhs, rhs } => { + self.traverse_expr0(lhs)?; + self.traverse_expr0(rhs)?; + } + ExprKind::UnaryOp { op, value } => { + self.traverse_expr0(value)?; + } + ExprKind::Call { callee, args } => (), + } - fn traverse_stmt(&mut self, stmt: &StmtKind) -> Result<(), Error> { - self.i += 1; + Ok(()) + } - match stmt { - StmtKind::Block(_) => todo!(), - StmtKind::ExprStmt(_) => todo!(), + fn traverse_stmt(&mut self, stmt: &Stmt) -> Result<(), Error> { + match &stmt.kind { + StmtKind::Block(children) => { + for child in children { + writeln!(&mut self.graph, "N{} -> N{};", stmt.id, child.id)?; + self.traverse_stmt(child)?; + } + } + StmtKind::ExprStmt(expr) => { + writeln!(&mut self.graph, "N{} -> N{};", stmt.id, expr.id)?; + self.traverse_expr(expr)?; + } StmtKind::IfStmt { - condition, - if_then, - else_then, - } => todo!(), - StmtKind::WhileStmt { condition, body } => todo!(), - StmtKind::DefineVariable { - identifier, - value, - typ, - } => todo!(), - StmtKind::AssignVariable { identifier, value } => todo!(), - StmtKind::DefineFunction { - identifier, - inputs, - output, - body, - } => todo!(), - StmtKind::Return(_) => todo!(), + if_then, else_then, .. + } => { + writeln!( + &mut self.graph, + "N{} -> N{} [label = \"If Then\"];", + stmt.id, if_then.id + )?; + self.traverse_stmt(if_then)?; + if let Some(else_then) = else_then { + writeln!( + &mut self.graph, + "N{} -> N{} [label = \"Else Then\"];", + stmt.id, else_then.id + )?; + self.traverse_stmt(else_then)?; + } + } + StmtKind::WhileStmt { condition, body } => { + writeln!( + &mut self.graph, + "N{} -> N{} [label = \"Condition\"];", + stmt.id, condition.id + )?; + writeln!( + &mut self.graph, + "N{} -> N{} [label = \"Body\"];", + stmt.id, body.id + )?; + self.traverse_expr(condition)?; + self.traverse_stmt(body)?; + } + StmtKind::DefineVariable { value, .. } => { + writeln!(&mut self.graph, "N{} -> N{};", stmt.id, value.id)?; + self.traverse_expr(value)?; + } + StmtKind::AssignVariable { value, .. } => { + writeln!(&mut self.graph, "N{} -> N{};", stmt.id, value.id)?; + self.traverse_expr(value)?; + } + StmtKind::DefineFunction { body, .. } => { + writeln!( + &mut self.graph, + "N{} -> N{} [label = \"Body\"];", + stmt.id, body.id + )?; + self.traverse_stmt(body)?; + } + StmtKind::Return(_) => (), } Ok(()) } - fn traverse_expr(&mut self, expr: &ExprKind) { - // + fn traverse_expr(&mut self, expr: &Expr) -> Result<(), Error> { + match &expr.kind { + ExprKind::Grouping(children) => { + writeln!(&mut self.graph, "N{} -> N{};", expr.id, children.id)?; + } + ExprKind::BinaryOp { lhs, rhs, .. } => { + writeln!(&mut self.graph, "N{} -> N{};", expr.id, lhs.id)?; + writeln!(&mut self.graph, "N{} -> N{};", expr.id, rhs.id)?; + } + ExprKind::UnaryOp { value, .. } => { + writeln!(&mut self.graph, "N{} -> N{};", expr.id, value.id)?; + } + ExprKind::Call { callee, args } => (), + _ => (), + } + + Ok(()) } } diff --git a/sloth/src/parser/mod.rs b/sloth/src/parser/mod.rs index 958166a..bc47ddd 100644 --- a/sloth/src/parser/mod.rs +++ b/sloth/src/parser/mod.rs @@ -3,7 +3,7 @@ pub mod expr; pub mod graph; pub mod stmt; -use self::ast::{Literal, StmtKind}; +use self::ast::{Literal, Stmt}; use crate::lexer::{Token, TokenType}; #[derive(thiserror::Error, Debug, PartialEq)] @@ -22,7 +22,7 @@ pub struct AstParser<'a> { } impl<'a> AstParser<'a> { - pub fn parse(tokens: Vec<Token<'a>>) -> Result<Vec<StmtKind>, ParsingError> { + pub fn parse(tokens: Vec<Token<'a>>) -> Result<Vec<Stmt>, ParsingError> { let mut parser = Self::new(tokens); let mut statements = Vec::new(); diff --git a/sloth/src/parser/stmt.rs b/sloth/src/parser/stmt.rs index f9980e3..c8913b4 100644 --- a/sloth/src/parser/stmt.rs +++ b/sloth/src/parser/stmt.rs @@ -1,9 +1,9 @@ -use super::ast::{FunctionInput, StmtKind}; +use super::ast::{FunctionInput, Stmt, StmtKind}; use super::{AstParser, ParsingError}; use crate::lexer::TokenType; impl<'a> AstParser<'a> { - pub(super) fn statement(&mut self) -> Result<StmtKind, ParsingError> { + pub(super) fn statement(&mut self) -> Result<Stmt, ParsingError> { match self.peek().tt { TokenType::OpeningBrace => self.block(), @@ -18,7 +18,7 @@ impl<'a> AstParser<'a> { } } - fn if_stmt(&mut self) -> Result<StmtKind, ParsingError> { + fn if_stmt(&mut self) -> Result<Stmt, ParsingError> { // Consume the if token self.consume(TokenType::If, "Expected if")?; @@ -36,28 +36,32 @@ impl<'a> AstParser<'a> { } } - Ok(StmtKind::IfStmt { + let kind = StmtKind::IfStmt { condition, if_then: if_then.into(), else_then: else_then.map(|it| it.into()), - }) + }; + + Ok(Stmt::new(self.reserve_id(), kind)) } - fn while_stmt(&mut self) -> Result<StmtKind, ParsingError> { + fn while_stmt(&mut self) -> Result<Stmt, ParsingError> { // Consume the while token self.consume(TokenType::While, "Expected while")?; let condition = self.expression()?; let body = self.block()?; - Ok(StmtKind::WhileStmt { + let kind = StmtKind::WhileStmt { condition, body: body.into(), - }) + }; + + Ok(Stmt::new(self.reserve_id(), kind)) } // TODO: Make variable types optional - fn define_variable(&mut self) -> Result<StmtKind, ParsingError> { + fn define_variable(&mut self) -> Result<Stmt, ParsingError> { // Consume the var token self.consume(TokenType::Var, "Expected var")?; @@ -72,15 +76,17 @@ impl<'a> AstParser<'a> { self.consume(TokenType::SemiColon, "Expected ';' at end of statement")?; - Ok(StmtKind::DefineVariable { + let kind = StmtKind::DefineVariable { identifier, value, typ, - }) + }; + + Ok(Stmt::new(self.reserve_id(), kind)) } // TODO: Make argument types optional - fn define_function(&mut self) -> Result<StmtKind, ParsingError> { + fn define_function(&mut self) -> Result<Stmt, ParsingError> { // Consume the fn token self.consume(TokenType::Fn, "Expected fn")?; @@ -113,36 +119,41 @@ impl<'a> AstParser<'a> { // Get the function body let body = self.block()?; - Ok(StmtKind::DefineFunction { + let kind = StmtKind::DefineFunction { identifier, inputs, output, body: body.into(), - }) + }; + + Ok(Stmt::new(self.reserve_id(), kind)) } - fn return_stmt(&mut self) -> Result<StmtKind, ParsingError> { + fn return_stmt(&mut self) -> Result<Stmt, ParsingError> { self.consume(TokenType::Return, "Expected return")?; let value = self.expression()?; self.consume(TokenType::SemiColon, "Expected ';' at end of statement")?; - Ok(StmtKind::Return(value)) + let kind = StmtKind::Return(value); + Ok(Stmt::new(self.reserve_id(), kind)) } - fn assign_variable(&mut self) -> Result<StmtKind, ParsingError> { + fn assign_variable(&mut self) -> Result<Stmt, ParsingError> { let identifier = self.consume_identifier()?; self.consume(TokenType::Eq, "Expected '='")?; let value = self.expression()?; self.consume(TokenType::SemiColon, "Expected ';' at end of statement")?; - Ok(StmtKind::AssignVariable { identifier, value }) + let kind = StmtKind::AssignVariable { identifier, value }; + Ok(Stmt::new(self.reserve_id(), kind)) } - fn expression_stmt(&mut self) -> Result<StmtKind, ParsingError> { + fn expression_stmt(&mut self) -> Result<Stmt, ParsingError> { let expr = self.expression()?; self.consume(TokenType::SemiColon, "Expected ';' at end of statement")?; - Ok(StmtKind::ExprStmt(expr)) + let kind = StmtKind::ExprStmt(expr); + Ok(Stmt::new(self.reserve_id(), kind)) } - fn block(&mut self) -> Result<StmtKind, ParsingError> { + fn block(&mut self) -> Result<Stmt, ParsingError> { // Consume the opening brace self.consume(TokenType::OpeningBrace, "Expected '{'")?; @@ -155,7 +166,9 @@ impl<'a> AstParser<'a> { // Consume the closing brace self.consume(TokenType::ClosingBrace, "Expected '}'")?; - Ok(StmtKind::Block(body)) + let kind = StmtKind::Block(body); + + Ok(Stmt::new(self.reserve_id(), kind)) } } |
