about summary refs log tree commit diff
path: root/src/parse/ast/expression.rs
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2021-10-20 22:15:08 +0200
committerMel <einebeere@gmail.com>2021-10-20 22:15:08 +0200
commita4980b8dbf1394c2b302f1de7c72d2264426b86e (patch)
tree97160332c53d8036ea3f6865ff60dabb2c55ef49 /src/parse/ast/expression.rs
parent8d5a74566beba45f4642838102c5a066ef2aa18d (diff)
downloadrabbithole-a4980b8dbf1394c2b302f1de7c72d2264426b86e.tar.zst
rabbithole-a4980b8dbf1394c2b302f1de7c72d2264426b86e.zip
Statement parsing.
Diffstat (limited to 'src/parse/ast/expression.rs')
-rw-r--r--src/parse/ast/expression.rs127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs
new file mode 100644
index 0000000..8563492
--- /dev/null
+++ b/src/parse/ast/expression.rs
@@ -0,0 +1,127 @@
+use std::fmt::{self, Display, Formatter};
+
+use super::value::{
+    BinaryOperator, Block, ConditionalBlock, FnHeader, Identifier, Literal, UnaryOperator,
+};
+
+#[derive(Debug)]
+pub enum Expression {
+    Binary {
+        left: Box<Expression>,
+        op: BinaryOperator,
+        right: Box<Expression>,
+    },
+    Unary {
+        op: UnaryOperator,
+        right: Box<Expression>,
+    },
+    Group(Box<Expression>),
+    Block(Box<Block>),
+    Fn {
+        header: FnHeader,
+        body: Box<Block>,
+    },
+    If {
+        conditionals: Vec<ConditionalBlock>,
+        else_block: Option<Box<Block>>,
+    },
+    Literal(Literal),
+    Identifier(Identifier),
+}
+
+impl Display for Expression {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        self.nested_fmt(f, 0)
+    }
+}
+
+impl Expression {
+    pub(crate) fn nested_fmt(&self, f: &mut Formatter<'_>, depth: usize) -> fmt::Result {
+        let pad = "  ".repeat(depth);
+        match self {
+            Expression::Binary { left, op, right } => {
+                writeln!(f, "{}Binary:", pad)?;
+                writeln!(f, "{}- Left:", pad)?;
+                left.nested_fmt(f, depth + 1)?;
+                writeln!(f, "{}- Operator: {:?}", pad, op)?;
+                writeln!(f, "{}- Right:", pad)?;
+                right.nested_fmt(f, depth + 1)?;
+            }
+            Expression::Unary { op, right } => {
+                writeln!(f, "{}Unary:", pad)?;
+                writeln!(f, "{}- Operator: {:?}", pad, op)?;
+                writeln!(f, "{}- Right:", pad)?;
+                right.nested_fmt(f, depth + 1)?;
+            }
+            Expression::Group(node) => {
+                writeln!(f, "{}Group:", pad)?;
+                node.nested_fmt(f, depth + 1)?;
+            }
+            Expression::Block(block) => {
+                Self::block_fmt(f, block, depth + 1)?;
+            }
+            Expression::Fn { header, body } => {
+                write!(f, "{}Fn (", pad)?;
+
+                // Write self receiver
+                if header.has_self_receiver {
+                    write!(f, "self, ")?;
+                }
+
+                // Write parameters
+                for p in header.parameters.iter() {
+                    write!(
+                        f,
+                        "{}: {}, ",
+                        p.identifier,
+                        p.type_constraint.as_ref().unwrap_or(&"_".into())
+                    )?;
+                }
+
+                // Write return type
+                writeln!(
+                    f,
+                    ") -> {}:",
+                    header.return_type.as_ref().unwrap_or(&"_".into())
+                )?;
+                Self::block_fmt(f, body, depth + 1)?;
+            }
+            Expression::Literal(literal) => {
+                writeln!(f, "{}Literal: {:?}", pad, literal)?;
+            }
+            Expression::Identifier(identifier) => {
+                writeln!(f, "{}Identifier: {:?}", pad, identifier)?;
+            }
+            Expression::If { conditionals, else_block } => {
+                writeln!(f, "{}If:", pad)?;
+                for (i, c) in conditionals.iter().enumerate() {
+                    writeln!(f, "{}- Condition {}:", pad, i)?;
+                    c.condition.nested_fmt(f, depth + 1)?;
+                    writeln!(f, "{}- Body {}:", pad, i)?;
+                    Self::block_fmt(f, &c.block, depth + 1)?;
+                }
+                if let Some(e) = else_block {
+                    writeln!(f, "{}- Else:", pad)?;
+                    Self::block_fmt(f, e, depth + 1)?;
+                }
+            },
+        }
+
+        Ok(())
+    }
+
+    fn block_fmt(f: &mut Formatter<'_>, block: &Block, depth: usize) -> fmt::Result {
+        let pad = "  ".repeat(depth);
+        writeln!(f, "{}Block:", pad)?;
+        for (i, statement) in block.statements.iter().enumerate() {
+            writeln!(f, "{}- {}:", pad, i)?;
+            statement.nested_fmt(f, depth + 1)?;
+        }
+        if let Some(tail_expression) = &block.tail_expression {
+            writeln!(f, "{}- Tail:", pad)?;
+            tail_expression.nested_fmt(f, depth + 1)?;
+        }
+
+        Ok(())
+    }
+}