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.rs117
-rw-r--r--src/parse/ast/nodes.rs176
-rw-r--r--src/parse/ast/statement.rs22
3 files changed, 202 insertions, 113 deletions
diff --git a/src/parse/ast/expression.rs b/src/parse/ast/expression.rs
index d119a71..e883aaa 100644
--- a/src/parse/ast/expression.rs
+++ b/src/parse/ast/expression.rs
@@ -1,34 +1,45 @@
 use std::fmt::{self, Display, Formatter};
 
-use crate::parse::ast::nodes::StrPart;
+use crate::lex::token::Location;
 
 use super::nodes::{
-    ArrayAccessNode, ArrayNode, BinaryOperator, BlockNode, CallNode, FnNode, Identifier, IfNode,
-    LoopNode, MemberAccessNode, SimpleLiteral, StrNode, UnaryOperator,
+    ArrayAccessExpression, ArrayExpression, BinaryOperatorNode, BlockExpression, CallExpression,
+    FnExpression, Identifier, IfExpression, LoopExpression, MemberAccessExpression,
+    SimpleLiteralNode, StrExpression, StrPartKind, UnaryOperatorNode,
 };
 
 #[derive(Debug, Clone)]
-pub enum Expression {
+pub struct Expression {
+    // TODO: Sometimes this location is duplicated for no reason,
+    // i.e. in the UnaryExpression, since the token for the UnaryOperatorNode
+    // will be the same as the location for the expression...
+    // Can we do something about it or is some duplication fine?
+    pub at: Location,
+    pub kind: ExpressionKind,
+}
+
+#[derive(Debug, Clone)]
+pub enum ExpressionKind {
     Binary {
         left: Box<Expression>,
-        op: BinaryOperator,
+        op: BinaryOperatorNode,
         right: Box<Expression>,
     },
     Unary {
-        op: UnaryOperator,
+        op: UnaryOperatorNode,
         right: Box<Expression>,
     },
-    Call(Box<CallNode>),
-    ArrayAccess(Box<ArrayAccessNode>),
-    MemberAccess(Box<MemberAccessNode>),
+    Call(Box<CallExpression>),
+    ArrayAccess(Box<ArrayAccessExpression>),
+    MemberAccess(Box<MemberAccessExpression>),
     Group(Box<Expression>),
-    Block(Box<BlockNode>),
-    If(Box<IfNode>),
-    Loop(Box<LoopNode>),
-    StrLiteral(Box<StrNode>),
-    FnLiteral(Box<FnNode>),
-    ArrayLiteral(ArrayNode),
-    SimpleLiteral(SimpleLiteral),
+    Block(Box<BlockExpression>),
+    If(Box<IfExpression>),
+    Loop(Box<LoopExpression>),
+    StrLiteral(Box<StrExpression>),
+    FnLiteral(Box<FnExpression>),
+    ArrayLiteral(ArrayExpression),
+    SimpleLiteral(SimpleLiteralNode),
     Identifier(Identifier),
 }
 
@@ -41,8 +52,8 @@ impl Display for Expression {
 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 } => {
+        match self.kind {
+            ExpressionKind::Binary { left, op, right } => {
                 writeln!(f, "{}Binary:", pad)?;
                 writeln!(f, "{}- Left:", pad)?;
                 left.nested_fmt(f, depth + 1)?;
@@ -50,63 +61,63 @@ impl Expression {
                 writeln!(f, "{}- Right:", pad)?;
                 right.nested_fmt(f, depth + 1)?;
             }
-            Expression::Unary { op, right } => {
+            ExpressionKind::Unary { op, right } => {
                 writeln!(f, "{}Unary:", pad)?;
                 writeln!(f, "{}- Operator: {:?}", pad, op)?;
                 writeln!(f, "{}- Right:", pad)?;
                 right.nested_fmt(f, depth + 1)?;
             }
-            Expression::Call(node) => {
+            ExpressionKind::Call(expr) => {
                 writeln!(f, "{}Function Call:", pad)?;
                 writeln!(f, "{}- Called:", pad)?;
-                node.called.nested_fmt(f, depth + 1)?;
-                for (i, e) in node.arguments.iter().enumerate() {
+                expr.called.nested_fmt(f, depth + 1)?;
+                for (i, e) in expr.arguments.iter().enumerate() {
                     writeln!(f, "{}- Argument {}:", pad, i)?;
                     e.nested_fmt(f, depth + 1)?;
                 }
             }
-            Expression::ArrayAccess(node) => {
+            ExpressionKind::ArrayAccess(expr) => {
                 writeln!(f, "{}Array Access:", pad)?;
                 writeln!(f, "{}- Array:", pad)?;
-                node.array.nested_fmt(f, depth + 1)?;
+                expr.array.nested_fmt(f, depth + 1)?;
                 writeln!(f, "{}- Index:", pad)?;
-                node.index.nested_fmt(f, depth + 1)?;
+                expr.index.nested_fmt(f, depth + 1)?;
             }
-            Expression::MemberAccess(node) => {
+            ExpressionKind::MemberAccess(expr) => {
                 writeln!(f, "{}Member Access:", pad)?;
                 writeln!(f, "{}- Object:", pad)?;
-                node.object.nested_fmt(f, depth + 1)?;
-                writeln!(f, "{}- Member Name: {}", pad, node.member_name)?;
+                expr.object.nested_fmt(f, depth + 1)?;
+                writeln!(f, "{}- Member Name: {}", pad, expr.member_name)?;
             }
-            Expression::Group(node) => {
+            ExpressionKind::Group(expr) => {
                 writeln!(f, "{}Group:", pad)?;
-                node.nested_fmt(f, depth + 1)?;
+                expr.nested_fmt(f, depth + 1)?;
             }
-            Expression::Block(block) => {
-                Self::block_fmt(f, block, depth + 1)?;
+            ExpressionKind::Block(expr) => {
+                Self::block_fmt(f, &expr, depth + 1)?;
             }
-            Expression::StrLiteral(node) => {
+            ExpressionKind::StrLiteral(expr) => {
                 writeln!(f, "{}Str:", pad)?;
-                for (i, statement) in node.parts.iter().enumerate() {
+                for (i, statement) in expr.parts.iter().enumerate() {
                     writeln!(f, "{}- {}:", pad, i)?;
-                    match statement {
-                        StrPart::Literal(literal) => {
+                    match statement.kind {
+                        StrPartKind::Literal(literal) => {
                             writeln!(f, "{}{}", "  ".repeat(depth + 1), literal.clone())
                         }
-                        StrPart::Embed(block) => block.nested_fmt(f, depth + 1),
+                        StrPartKind::Embed(block) => block.nested_fmt(f, depth + 1),
                     }?;
                 }
             }
-            Expression::FnLiteral(node) => {
+            ExpressionKind::FnLiteral(expr) => {
                 write!(f, "{}Fn (", pad)?;
 
                 // Write self receiver
-                if node.header.has_self_receiver {
+                if expr.header.has_self_receiver {
                     write!(f, "self, ")?;
                 }
 
                 // Write parameters
-                for p in node.header.parameters.iter() {
+                for p in expr.header.parameters.iter() {
                     write!(
                         f,
                         "{}: {}, ",
@@ -119,52 +130,52 @@ impl Expression {
                 writeln!(
                     f,
                     ") -> {}:",
-                    node.header.return_type.as_ref().unwrap_or(&"_".into())
+                    expr.header.return_type.as_ref().unwrap_or(&"_".into())
                 )?;
-                Self::block_fmt(f, &node.body, depth + 1)?;
+                Self::block_fmt(f, &expr.body, depth + 1)?;
             }
-            Expression::ArrayLiteral(node) => {
+            ExpressionKind::ArrayLiteral(expr) => {
                 writeln!(f, "{}Array Literal:", pad)?;
-                for (i, c) in node.elements.iter().enumerate() {
+                for (i, c) in expr.elements.iter().enumerate() {
                     writeln!(f, "{}- Element {}:", pad, i)?;
                     c.nested_fmt(f, depth + 1)?;
                 }
             }
-            Expression::SimpleLiteral(literal) => {
+            ExpressionKind::SimpleLiteral(literal) => {
                 writeln!(f, "{}Literal: {:?}", pad, literal)?;
             }
-            Expression::Identifier(identifier) => {
+            ExpressionKind::Identifier(identifier) => {
                 writeln!(f, "{}Identifier: {:?}", pad, identifier)?;
             }
-            Expression::If(node) => {
+            ExpressionKind::If(expr) => {
                 writeln!(f, "{}If:", pad)?;
-                for (i, c) in node.conditionals.iter().enumerate() {
+                for (i, c) in expr.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) = &node.else_block {
+                if let Some(e) = &expr.else_block {
                     writeln!(f, "{}- Else:", pad)?;
                     Self::block_fmt(f, e, depth + 1)?;
                 }
             }
-            Expression::Loop(node) => {
+            ExpressionKind::Loop(expr) => {
                 writeln!(f, "{}Loop:", pad)?;
-                if let Some(loop_condition) = &node.condition {
+                if let Some(loop_condition) = &expr.condition {
                     writeln!(f, "{}- Condition:", pad)?;
                     loop_condition.nested_fmt(f, depth + 1)?;
                 }
 
                 writeln!(f, "{}- Body:", pad)?;
-                Self::block_fmt(f, &node.body, depth + 1)?;
+                Self::block_fmt(f, &expr.body, depth + 1)?;
             }
         }
 
         Ok(())
     }
 
-    fn block_fmt(f: &mut Formatter<'_>, block: &BlockNode, depth: usize) -> fmt::Result {
+    fn block_fmt(f: &mut Formatter<'_>, block: &BlockExpression, depth: usize) -> fmt::Result {
         let pad = "  ".repeat(depth);
         writeln!(f, "{}Block:", pad)?;
         for (i, statement) in block.statements.iter().enumerate() {
diff --git a/src/parse/ast/nodes.rs b/src/parse/ast/nodes.rs
index 16d0eaa..4eff251 100644
--- a/src/parse/ast/nodes.rs
+++ b/src/parse/ast/nodes.rs
@@ -1,9 +1,23 @@
-use crate::lex::token::{Token, TokenKind::*};
+//! Nodes are parts of an expression, but aren't expressions themselves.
+//! Example: A BinaryExpression is made out of two expressions and an operator node,
+//! because an operator can't be an expression by itself.
+//!
+//! Nodes can also contain nested expressions.
+//! This module also contains the actual expression structs for this reason,
+//! although this might be changed later?
+
+use crate::lex::token::{Location, Token, TokenKind::*};
 
 use super::{expression::Expression, statement::Statement};
 
+#[derive(Debug, Clone)]
+pub struct BinaryOperatorNode {
+    pub at: Location,
+    pub kind: BinaryOperatorKind,
+}
+
 #[derive(Debug, Clone, Copy)]
-pub enum BinaryOperator {
+pub enum BinaryOperatorKind {
     Plus,
     Minus,
     Star,
@@ -21,140 +35,196 @@ pub enum BinaryOperator {
     Dot,
 }
 
-impl BinaryOperator {
+impl BinaryOperatorNode {
     pub fn from_token(token: Token) -> Self {
-        match token.kind {
-            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,
-            OpAnd => Self::And,
-            OpOr => Self::Or,
-            Assign => Self::Assign,
-            ConstAssign => Self::ConstAssign,
-            Dot => Self::Dot,
+        use BinaryOperatorKind as Kind;
+
+        let kind = match token.kind {
+            OpPlus => Kind::Plus,
+            OpMinus => Kind::Minus,
+            OpStar => Kind::Star,
+            OpSlash => Kind::Slash,
+            OpEq => Kind::Eq,
+            OpNeq => Kind::Neq,
+            OpLt => Kind::Lt,
+            OpGt => Kind::Gt,
+            OpLte => Kind::Lte,
+            OpGte => Kind::Gte,
+            OpAnd => Kind::And,
+            OpOr => Kind::Or,
+            Assign => Kind::Assign,
+            ConstAssign => Kind::ConstAssign,
+            Dot => Kind::Dot,
             _ => panic!("Can't create binary operator from '{:?}'.", token.kind),
+        };
+
+        Self {
+            at: token.location,
+            kind,
         }
     }
 }
 
+#[derive(Debug, Clone)]
+pub struct UnaryOperatorNode {
+    pub at: Location,
+    pub kind: UnaryOperatorKind,
+}
+
 #[derive(Debug, Clone, Copy)]
-pub enum UnaryOperator {
+pub enum UnaryOperatorKind {
     Minus,
     Not,
 }
 
-impl UnaryOperator {
+impl UnaryOperatorNode {
     pub fn from_token(token: Token) -> Self {
-        match token.kind {
-            OpMinus => Self::Minus,
-            OpNot => Self::Not,
+        use UnaryOperatorKind as Kind;
+
+        let kind = match token.kind {
+            OpMinus => Kind::Minus,
+            OpNot => Kind::Not,
             _ => panic!("Can't create unary operator from '{:?}'.", token.kind),
+        };
+
+        Self {
+            at: token.location,
+            kind,
         }
     }
 }
 
 #[derive(Debug, Clone)]
-pub enum SimpleLiteral {
+pub struct SimpleLiteralNode {
+    pub at: Location,
+    pub kind: SimpleLiteralKind,
+}
+
+#[derive(Debug, Clone)]
+pub enum SimpleLiteralKind {
     Int(u32),
     Float(f32),
     Bool(bool),
 }
 
-impl SimpleLiteral {
+impl SimpleLiteralNode {
     pub fn from_token(token: Token) -> Self {
-        match token.kind {
-            Int(int) => Self::Int(int),
-            Float(float) => Self::Float(float),
-            KeywordTrue => Self::Bool(true),
-            KeywordFalse => Self::Bool(false),
+        use SimpleLiteralKind as Kind;
+
+        let kind = match token.kind {
+            Int(int) => Kind::Int(int),
+            Float(float) => Kind::Float(float),
+            KeywordTrue => Kind::Bool(true),
+            KeywordFalse => Kind::Bool(false),
             _ => panic!("Can't create literal from '{:?}'.", token.kind),
+        };
+
+        Self {
+            at: token.location,
+            kind,
         }
     }
 }
 
 pub type Identifier = String;
 
-// If the contraint is None the type will have to be inferred
+// If the constraint is None the type will have to be inferred
 // during analysis.
 #[derive(Debug, Clone)]
-pub struct TypedIdentifier {
+pub struct TypedIdentifierNode {
+    // TODO: Add locations to other parts, not just the start of the identifier.
+    // i.e. make an IdentifierNode or something like that.
+    pub at: Location,
     pub identifier: Identifier,
     pub type_constraint: Option<Identifier>,
 }
 
 #[derive(Debug, Clone)]
-pub struct CallNode {
+pub struct CallExpression {
+    // TODO: Ditto.
+    pub at: Location,
     pub called: Expression,
     pub arguments: Vec<Expression>,
 }
 
 #[derive(Debug, Clone)]
-pub struct ArrayAccessNode {
+pub struct ArrayAccessExpression {
+    pub at: Location,
     pub array: Expression,
     pub index: Expression,
 }
 
 #[derive(Debug, Clone)]
-pub struct MemberAccessNode {
+pub struct MemberAccessExpression {
+    // TODO: Ditto.
+    pub at: Location,
     pub object: Expression,
     pub member_name: Identifier,
 }
 
 #[derive(Debug, Clone)]
-pub struct StrNode {
-    pub parts: Vec<StrPart>,
+pub struct StrExpression {
+    pub at: Location,
+    pub parts: Vec<StrPartNode>,
+}
+
+#[derive(Debug, Clone)]
+pub struct StrPartNode {
+    pub at: Location,
+    pub kind: StrPartKind,
 }
 
 #[derive(Debug, Clone)]
-pub enum StrPart {
+pub enum StrPartKind {
     Literal(String),
     Embed(Expression),
 }
 
 #[derive(Debug, Clone)]
-pub struct FnNode {
-    pub header: FnHeader,
-    pub body: BlockNode,
+pub struct FnExpression {
+    pub at: Location,
+    pub header: FnHeaderNode,
+    pub body: BlockExpression,
 }
 
 #[derive(Debug, Clone)]
-pub struct FnHeader {
+pub struct FnHeaderNode {
+    // TODO: ditto...
+    pub at: Location,
     pub has_self_receiver: bool,
-    pub parameters: Vec<TypedIdentifier>,
+    pub parameters: Vec<TypedIdentifierNode>,
     pub return_type: Option<Identifier>,
 }
 
 #[derive(Debug, Clone)]
-pub struct ArrayNode {
+pub struct ArrayExpression {
+    pub at: Location,
     pub elements: Vec<Expression>,
 }
 #[derive(Debug, Clone)]
-pub struct IfNode {
-    pub conditionals: Vec<ConditionalBlock>,
-    pub else_block: Option<BlockNode>,
+pub struct IfExpression {
+    pub at: Location,
+    pub conditionals: Vec<ConditionalBlockNode>,
+    pub else_block: Option<BlockExpression>,
 }
 
 #[derive(Debug, Clone)]
-pub struct LoopNode {
+pub struct LoopExpression {
+    pub at: Location,
     pub condition: Option<Expression>,
-    pub body: BlockNode,
+    pub body: BlockExpression,
 }
 
 #[derive(Debug, Clone)]
-pub struct BlockNode {
+pub struct BlockExpression {
+    pub at: Location,
     pub statements: Vec<Statement>,
     pub tail_expression: Option<Expression>,
 }
 
 #[derive(Debug, Clone)]
-pub struct ConditionalBlock {
+pub struct ConditionalBlockNode {
+    pub at: Location,
     pub condition: Expression,
-    pub block: BlockNode,
+    pub block: BlockExpression,
 }
diff --git a/src/parse/ast/statement.rs b/src/parse/ast/statement.rs
index 99ee0e0..7eb9978 100644
--- a/src/parse/ast/statement.rs
+++ b/src/parse/ast/statement.rs
@@ -1,9 +1,17 @@
 use std::fmt::Display;
 
+use crate::lex::token::Location;
+
 use super::expression::Expression;
 
 #[derive(Debug, Clone)]
-pub enum Statement {
+pub struct Statement {
+    pub at: Location,
+    pub kind: StatementKind,
+}
+
+#[derive(Debug, Clone)]
+pub enum StatementKind {
     Expression(Expression),
     Print(Expression),
     Break(Option<Expression>),
@@ -24,17 +32,17 @@ impl Statement {
         depth: usize,
     ) -> std::fmt::Result {
         let pad = "  ".repeat(depth);
-        match self {
-            Statement::Expression(expression) => expression.nested_fmt(f, depth)?,
-            Statement::Print(expression) => {
+        match self.kind {
+            StatementKind::Expression(expression) => expression.nested_fmt(f, depth)?,
+            StatementKind::Print(expression) => {
                 writeln!(f, "{}Print:", pad)?;
                 expression.nested_fmt(f, depth + 1)?;
             }
-            Statement::Return(expression) => {
+            StatementKind::Return(expression) => {
                 writeln!(f, "{}Return:", pad)?;
                 expression.nested_fmt(f, depth + 1)?;
             }
-            Statement::Break(expression) => {
+            StatementKind::Break(expression) => {
                 if let Some(returned_on_break) = expression {
                     writeln!(f, "{}Break:", pad)?;
                     returned_on_break.nested_fmt(f, depth + 1)?;
@@ -42,7 +50,7 @@ impl Statement {
                     writeln!(f, "{}Break", pad)?;
                 }
             }
-            Statement::Continue => {
+            StatementKind::Continue => {
                 writeln!(f, "{}Continue", pad)?;
             }
         }