aboutsummaryrefslogtreecommitdiff
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,
+}