about summary refs log tree commit diff
path: root/src/parse/ast
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse/ast')
-rw-r--r--src/parse/ast/expression.rs127
-rw-r--r--src/parse/ast/mod.rs21
-rw-r--r--src/parse/ast/statement.rs39
-rw-r--r--src/parse/ast/value.rs106
4 files changed, 293 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(())
+    }
+}
diff --git a/src/parse/ast/mod.rs b/src/parse/ast/mod.rs
new file mode 100644
index 0000000..257675f
--- /dev/null
+++ b/src/parse/ast/mod.rs
@@ -0,0 +1,21 @@
+use std::fmt::Display;
+
+use self::statement::Statement;
+
+pub mod expression;
+pub mod statement;
+pub mod value;
+
+#[derive(Debug)]
+pub struct Program {
+    pub statements: Vec<Statement>,
+}
+
+impl Display for Program {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        for statement in self.statements.iter() {
+            writeln!(f, "{}", statement)?;
+        }
+        Ok(())
+    }
+}
diff --git a/src/parse/ast/statement.rs b/src/parse/ast/statement.rs
new file mode 100644
index 0000000..eec589e
--- /dev/null
+++ b/src/parse/ast/statement.rs
@@ -0,0 +1,39 @@
+use std::fmt::Display;
+
+use super::expression::Expression;
+
+#[derive(Debug)]
+pub enum Statement {
+    Expression(Expression),
+    Print(Expression),
+    Return(Expression),
+}
+
+impl Display for Statement {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.nested_fmt(f, 0)
+    }
+}
+
+impl Statement {
+    pub(crate) fn nested_fmt(
+        &self,
+        f: &mut std::fmt::Formatter<'_>,
+        depth: usize,
+    ) -> std::fmt::Result {
+        let pad = "  ".repeat(depth);
+        match self {
+            Statement::Expression(expression) => expression.nested_fmt(f, depth)?,
+            Statement::Print(expression) => {
+                writeln!(f, "{}Print:", pad)?;
+                expression.nested_fmt(f, depth + 1)?;
+            }
+            Statement::Return(expression) => {
+                writeln!(f, "{}Return:", pad)?;
+                expression.nested_fmt(f, depth + 1)?;
+            }
+        }
+
+        Ok(())
+    }
+}
diff --git a/src/parse/ast/value.rs b/src/parse/ast/value.rs
new file mode 100644
index 0000000..263cb58
--- /dev/null
+++ b/src/parse/ast/value.rs
@@ -0,0 +1,106 @@
+use crate::lex::token::{Token, TokenVariant::*};
+
+use super::{expression::Expression, statement::Statement};
+
+#[derive(Debug)]
+pub enum BinaryOperator {
+    Plus,
+    Minus,
+    Star,
+    Slash,
+    Eq,
+    Neq,
+    Gt,
+    Gte,
+    Lt,
+    Lte,
+    Assign,
+    ConstAssign,
+    Dot,
+}
+
+impl BinaryOperator {
+    pub fn from_token(token: Token) -> Self {
+        match token.variant {
+            OpPlus => Self::Plus,
+            OpMinus => Self::Minus,
+            OpStar => Self::Star,
+            OpSlash => Self::Slash,
+            OpEq => Self::Eq,
+            OpNeq => Self::Neq,
+            OpLt => Self::Lt,
+            OpGt => Self::Gt,
+            OpLte => Self::Lte,
+            OpGte => Self::Gte,
+            Assign => Self::Assign,
+            ConstAssign => Self::ConstAssign,
+            Dot => Self::Dot,
+            _ => panic!("Can't create binary operator from '{:?}'.", token.variant)
+        }
+    }
+}
+
+#[derive(Debug)]
+pub enum UnaryOperator {
+    Plus,
+    Minus,
+    Not,
+}
+
+impl UnaryOperator {
+    pub fn from_token(token: Token) -> Self {
+        match token.variant {
+            OpPlus => Self::Plus,
+            OpMinus => Self::Minus,
+            OpNot => Self::Not,
+            _ => panic!("Can't create unary operator from '{:?}'.", token.variant)
+        }
+    }
+}
+
+#[derive(Debug)]
+pub enum Literal {
+    Int(u32),
+    Float(f32),
+    Str(String),
+}
+
+impl Literal {
+    pub fn from_token(token: Token) -> Self {
+        match token.variant {
+            Int(int) => Self::Int(int),
+            Float(float) => Self::Float(float),
+            Str(string) => Self::Str(string),
+            _ => panic!("Can't create literal from '{:?}'.", token.variant)
+        }
+    }
+}
+
+pub type Identifier = String;
+
+// If the contraint is None the type will have to be inferred
+// during analysis.
+#[derive(Debug)]
+pub struct TypedIdentifier {
+    pub identifier: Identifier,
+    pub type_constraint: Option<Identifier>,
+}
+
+#[derive(Debug)]
+pub struct FnHeader {
+    pub has_self_receiver: bool,
+    pub parameters: Vec<TypedIdentifier>,
+    pub return_type: Option<Identifier>,
+}
+
+#[derive(Debug)]
+pub struct Block {
+    pub statements: Vec<Statement>,
+    pub tail_expression: Option<Expression>,
+}
+
+#[derive(Debug)]
+pub struct ConditionalBlock {
+    pub condition: Expression,
+    pub block: Block,
+}