From 8c07dd63eb3e4c10e5c7b6c2ef773c1fbe913196 Mon Sep 17 00:00:00 2001 From: Vedat Can Keklik Date: Mon, 4 Dec 2023 21:40:47 +0300 Subject: [PATCH] fix: JSON for visualization --- src/lang/mod.rs | 2 +- src/lang/serializer.rs | 193 ++++++++++++++++++++++++++++++++++ src/lang/visualization.rs | 215 -------------------------------------- src/runtime/mod.rs | 2 +- 4 files changed, 195 insertions(+), 217 deletions(-) create mode 100644 src/lang/serializer.rs delete mode 100644 src/lang/visualization.rs diff --git a/src/lang/mod.rs b/src/lang/mod.rs index 18c185d3..7f5013a6 100644 --- a/src/lang/mod.rs +++ b/src/lang/mod.rs @@ -1,6 +1,6 @@ pub mod ast; pub mod parser; pub mod scanner; +pub mod serializer; mod tests; pub mod token; -mod visualization; diff --git a/src/lang/serializer.rs b/src/lang/serializer.rs new file mode 100644 index 00000000..db881c4f --- /dev/null +++ b/src/lang/serializer.rs @@ -0,0 +1,193 @@ +use serde_json::{json, Value}; + +use super::{ + ast::{ + expr::{Expr, ExprId}, + stmt::{Stmt, StmtId}, + Visitor, + }, + parser::Parsed, +}; +use std::rc::Rc; + +impl Parsed { + pub fn serialize(&mut self) -> String { + serde_json::to_string_pretty(&json!({ + "type": "Program", + "body": self.statements.clone().iter().map(|stmt| self.visit_stmt(*stmt).unwrap()).collect::>() + })).unwrap() + } +} + +impl Visitor for Parsed { + fn visit_expr(&mut self, eidx: ExprId) -> Result { + // TODO: Remove clone here + let a = Rc::clone(&self.arena); + let e = a.get_expression(eidx); + + let matched: Value = match e { + Expr::Select(val) => json!({ + "type": "Expr::Select", + // TODO(vck): Implement rest of the select + }), + Expr::Literal(val) => { + json!({ + "type": "Expr::Literal", + "value": format!("{:?}", val), + }) + } + Expr::Grouping(expr) => { + json!({ + "type": "Expr::Grouping", + "value": self.visit_expr(*expr)?, + }) + } + Expr::Unary { token, expr } => { + json!({ + "type": "Expr::Unary", + "operator": token.span.lexeme.as_ref(), + "value": self.visit_expr(*expr)?, + }) + } + Expr::Binary { token, left, right } => { + json!({ + "type": "Expr::Binary", + "left": self.visit_expr(*left)?, + "operator": token.span.lexeme.as_ref(), + "right": self.visit_expr(*right)?, + }) + } + Expr::Variable(tok) => { + json!({ + "type": "Expr::Variable", + "value": tok.span.lexeme.as_ref(), + }) + } + Expr::Assignment { var_tok, expr } => { + json!({ + "type": "Expr::Assignment", + "variable": var_tok.span.lexeme.as_ref(), + "value": self.visit_expr(*expr)?, + }) + } + Expr::Logical { left, token, right } => { + json!({ + "type": "Expr::Logical", + "left": self.visit_expr(*left)?, + "operator": token.span.lexeme.as_ref(), + "right": self.visit_expr(*right)?, + }) + } + Expr::Call { + callee, + paren: _, + args, + } => { + json!({ + "type": "Expr::Call", + "callee": self.visit_expr(*callee)?, + "args": args.iter().map(|arg| self.visit_expr(*arg).unwrap()).collect::>(), + }) + } + Expr::Function { + name, + parameters, + body, + } => { + let fn_name = if name.is_some() { + name.as_ref().unwrap().span.lexeme.as_ref() + } else { + "" + }; + json!({ + "type": "Expr::Function", + "name": fn_name, + "parameters": parameters.iter().map(|param| param.span.lexeme.as_ref()).collect::>(), + "body": body.iter().map(|stmt| self.visit_stmt(*stmt).unwrap()).collect::>(), + }) + } + }; + + Ok(matched) + } + + fn visit_stmt(&mut self, sidx: StmtId) -> Result { + // TODO: Remove clone here + let a = Rc::clone(&self.arena); + let s = a.get_statement(sidx); + let matched: Value = match s { + Stmt::Expression(expr) => { + json!({ + "type": "Stmt::Expression", + "value": self.visit_expr(*expr)?, + }) + } + Stmt::Declaration { token, expr } => { + json!({ + "type": "Stmt::Declaration", + "variable": token.span.lexeme.as_ref(), + "value": self.visit_expr(*expr)?, + }) + } + Stmt::Block(statements) => { + json!({ + "type": "Stmt::Block", + "body": statements.iter().map(|stmt| self.visit_stmt(*stmt).unwrap()).collect::>(), + }) + } + Stmt::If { + condition, + body, + r#else, + } => { + json!({ + "type": "Stmt::If", + "condition": self.visit_expr(*condition)?, + "body": self.visit_stmt(*body)?, + "else": if r#else.is_some() { + self.visit_stmt(r#else.unwrap())? + } else { + json!("None") + }, + }) + } + Stmt::Loop { + condition, + body, + post, + } => { + json!({ + "type": "Stmt::Loop", + "condition": if condition.is_some() { + self.visit_expr(condition.unwrap())? + } else { + json!("None") + }, + "body": self.visit_stmt(*body)?, + "post": if post.is_some() { + self.visit_stmt(post.unwrap())? + } else { + json!("None") + }, + }) + } + Stmt::Break(_) => json!({ + "type": "Stmt::Break", + }), + Stmt::Continue(_) => json!({ + "type": "Stmt::Continue", + }), + Stmt::Return { token: _, expr } => { + json!({ + "type": "Stmt::Return", + "value": if expr.is_some() { + self.visit_expr(expr.unwrap())? + } else { + json!("None") + }, + }) + } + }; + Ok(matched) + } +} diff --git a/src/lang/visualization.rs b/src/lang/visualization.rs deleted file mode 100644 index c5fda76d..00000000 --- a/src/lang/visualization.rs +++ /dev/null @@ -1,215 +0,0 @@ -use std::{ - fmt::{Debug, Display, Formatter}, - rc::Rc, -}; - -use super::parser::Parsed; -use crate::lang::ast::expr::{Expr, ExprId}; -use crate::lang::ast::stmt::{Stmt, StmtId}; - -fn indent(level: u32, str: &str, terminate: bool) -> String { - if terminate { - return format!( - "{}{}└──{}", - "\n".to_owned(), - "│ ".repeat(level as usize).as_str(), - str - ); - } - format!( - "{}{}├──{}", - "\n".to_owned(), - "│ ".repeat(level as usize).as_str(), - str - ) -} - -impl Parsed { - fn visit_expr(&self, eidx: ExprId, level: u32) -> Result { - // TODO: Remove clone here - let a = Rc::clone(&self.arena); - let e = a.get_expression(eidx); - - let matched: String = match e { - Expr::Select(val) => format!("Select ({:?})", val), - Expr::Literal(val) => indent(level, &format!("Literal ({:?})", val), true), - Expr::Grouping(expr) => self.visit_expr(*expr, level + 1)?, - Expr::Unary { token, expr } => { - let buf = format!( - "{}{}{}", - &indent(level, "Unary", false), - &indent(level + 1, &format!("{:?}", token), false), - &self.visit_expr(*expr, level + 1)?, - ); - buf - } - Expr::Binary { token, left, right } => { - format!( - "{}{}{}", - &indent( - level, - &format!("Binary ({})", token.span.lexeme.as_ref()), - false - ), - &self.visit_expr(*left, level + 1)?, - &self.visit_expr(*right, level + 1)? - ) - } - Expr::Variable(tok) => indent( - level, - &format!("Variable ({})", tok.span.lexeme.as_ref()), - false, - ), - Expr::Assignment { var_tok, expr } => { - let buf = format!( - "{}{}", - &indent( - level + 1, - &format!("Assignment ({})", var_tok.span.lexeme.as_ref()), - false - ), - &self.visit_expr(*expr, level + 1)?, - ); - buf - } - Expr::Logical { left, token, right } => { - let mut buf = format!( - "{}{}{}", - &indent(level, "Logical", false), - &indent(level + 1, &format!("{:?}", token), false), - &self.visit_expr(*left, level + 1)?, - ); - buf.push_str(&self.visit_expr(*right, level + 1)?); - buf - } - Expr::Call { - callee, - paren: _, - args, - } => { - let mut buf = format!( - "{}{}", - &indent(level, "Call", false), - &self.visit_expr(*callee, level + 1)?, - ); - for arg in args { - buf.push_str(&self.visit_expr(*arg, level + 1)?); - } - buf - } - Expr::Function { - name, - parameters, - body, - } => { - let fn_name = if name.is_some() { - name.as_ref().unwrap().span.lexeme.as_ref() - } else { - "" - }; - let mut buf = indent(level, &format!("FunctionDeclaration [{} (", fn_name), false); - for param in parameters { - buf.push_str(&format!("{},", param.span.lexeme.as_ref())); - } - buf.push_str(")]"); - for stmt in body.as_ref() { - buf.push_str(&self.visit_stmt(*stmt, level + 1)?); - } - buf - } - }; - - Ok(matched) - } - - fn visit_stmt(&self, sidx: StmtId, level: u32) -> Result { - // TODO: Remove clone here - let a = Rc::clone(&self.arena); - let s = a.get_statement(sidx); - match s { - Stmt::Expression(expr) => { - let mut buf = indent(level, "ExprStmt", false); - buf.push_str(&self.visit_expr(*expr, level + 1)?); - Ok(buf) - } - Stmt::Declaration { token, expr } => { - let mut buf = indent( - level, - &format!("Declaration ({})", token.span.lexeme.as_ref()), - false, - ); - buf.push_str(&self.visit_expr(*expr, level + 1)?); - Ok(buf) - } - Stmt::Block(statements) => { - let mut buf = indent(level, "Block", false); - for statement in statements { - buf.push_str(&self.visit_stmt(*statement, level + 1)?); - } - Ok(buf) - } - Stmt::If { - condition, - body, - r#else, - } => { - let mut buf = format!( - "{}{}{}", - &indent(level, "If", false), - &self.visit_expr(*condition, level + 1)?, - &self.visit_stmt(*body, level + 1)?, - ); - if let Some(else_stmt) = r#else { - buf.push_str(&indent( - level, - &format!("Else {}", &self.visit_stmt(*else_stmt, level + 1)?), - false, - )); - } - buf.push_str(&indent(level, "", false)); - Ok(buf) - } - Stmt::Loop { - condition, - body, - post, - } => Ok(format!( - "{}{}{}{}", - &indent(level, "Loop", false), - &self.visit_expr(*condition.as_ref().unwrap(), level + 1)?, - &self.visit_stmt(*body, level + 1)?, - &self.visit_stmt(*post.as_ref().unwrap(), level + 1)? - )), - Stmt::Break(_) => Ok(indent(level, "Break", false)), - Stmt::Continue(_) => Ok(indent(level, "Continue", false)), - Stmt::Return { token: _, expr } => { - let mut buf = indent(level, "Return", false); - if expr.is_some() { - buf.push_str(&self.visit_expr(expr.unwrap(), level + 1)?); - } - Ok(buf) - } - } - } - - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let mut buf = "Program".to_owned(); - for stmt in &self.statements { - buf.push_str(&self.visit_stmt(*stmt, 0).unwrap()); - } - writeln!(f, "{}", buf)?; - Ok(()) - } -} - -impl Display for Parsed { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - self.fmt(f) - } -} - -impl Debug for Parsed { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - self.fmt(f) - } -} diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs index 096d9871..2b1acfdf 100644 --- a/src/runtime/mod.rs +++ b/src/runtime/mod.rs @@ -82,7 +82,7 @@ impl Runtime { pub fn print_ast(&mut self, source: &str) { let tokens = Scanner::scan(source).unwrap(); let parsed = Parser::parse(&tokens); - println!("{:?}", parsed); + println!("{}", parsed.unwrap().serialize()); } pub fn interpret(&mut self, source: &str) -> Result {