about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/error.rs110
-rw-r--r--src/interpret/operator.rs32
-rw-r--r--src/interpret/walker.rs108
-rw-r--r--src/main.rs11
-rw-r--r--src/parse/macros.rs4
-rw-r--r--src/parse/parser.rs85
6 files changed, 205 insertions, 145 deletions
diff --git a/src/error.rs b/src/error.rs
index 227a4b0..ed92355 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,10 +1,14 @@
-use crate::{interpret::walker::WalkerError, lex::token::Location, parse::parser::ParserError};
+use crate::{
+    interpret::walker::WalkerError,
+    lex::token::Location,
+    parse::parser::{ParserError, ParserErrorLocation},
+};
 use colored::Colorize;
 use std::fmt::Display;
 
-pub struct RHError {
-    pub at: ErrorLocation,
-    pub kind: RHErrorKind,
+pub enum RHError {
+    Parse(ParserError),
+    Run(WalkerError),
 }
 
 impl RHError {
@@ -16,16 +20,6 @@ impl RHError {
     }
 }
 
-pub enum RHErrorKind {
-    Parse(ParserError),
-    Run(WalkerError),
-}
-
-pub enum ErrorLocation {
-    Specific(Location),
-    Eof,
-}
-
 pub struct RHErrorWithSource<'source> {
     error: RHError,
     source: &'source str,
@@ -33,45 +27,27 @@ pub struct RHErrorWithSource<'source> {
 
 impl Display for RHErrorWithSource<'_> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let (error_title, error_string) = match &self.error.kind {
-            RHErrorKind::Parse(parser_error) => (
+        let (error_title, error_string) = match &self.error {
+            RHError::Parse(parser_error) => (
                 "Encountered error during parsing",
-                format!("{}", parser_error),
+                format!("{}", parser_error.kind),
             ),
-            RHErrorKind::Run(walker_error) => {
-                ("Encountered runtime error", format!("{}", walker_error))
-            }
-        };
-
-        let weird_source_error_msg =
-            "Found error but could not get it's location in source, how does this even happen?";
-
-        let (line_number, line_column, source_line) = match self.error.at {
-            ErrorLocation::Specific(location) => (
-                location.row,
-                location.col,
-                self.source
-                    .lines()
-                    .nth(location.row)
-                    .expect(weird_source_error_msg),
+            RHError::Run(walker_error) => (
+                "Encountered runtime error",
+                format!("{}", walker_error.kind),
             ),
-            ErrorLocation::Eof => {
-                let lines = self.source.lines();
-                let (line_count, _) = lines.size_hint();
-                let last_line = lines.last().expect(weird_source_error_msg);
-
-                (line_count, last_line.len(), last_line)
-            }
         };
 
-        let arrow_pad_len = line_column + 3 + line_number.to_string().len();
+        let at = MappedErrorLocation::new(self);
+
+        let arrow_pad_len = at.line_column + 3 + at.line_number.to_string().len();
 
         writeln!(f, "{} {}:\n", " Error ".on_red(), error_title)?;
         writeln!(
             f,
             "{}{}",
-            format!("{} | ", line_number).dimmed(),
-            source_line
+            format!("{} | ", at.line_number).dimmed(),
+            at.source_line
         )?;
         writeln!(f, "{}{}", " ".repeat(arrow_pad_len), "^".red())?;
         writeln!(f, "{}", error_string)?;
@@ -79,3 +55,51 @@ impl Display for RHErrorWithSource<'_> {
         Ok(())
     }
 }
+
+pub struct MappedErrorLocation<'s> {
+    line_number: usize,
+    line_column: usize,
+    source_line: &'s str,
+}
+
+impl<'s> MappedErrorLocation<'s> {
+    const SOURCE_MISSING_ERROR_LOCATION: &'static str =
+        "Found error but could not get it's location in source, how does this even happen?";
+
+    fn new(from: &'s RHErrorWithSource<'s>) -> MappedErrorLocation<'s> {
+        match &from.error {
+            RHError::Parse(error) => match &error.at {
+                ParserErrorLocation::Specific(at) => Self::at_location(from, at),
+                ParserErrorLocation::Eof => Self::last_line(from),
+            },
+            RHError::Run(error) => Self::at_location(from, &error.at),
+        }
+    }
+
+    fn last_line(from: &'s RHErrorWithSource<'s>) -> MappedErrorLocation<'s> {
+        let lines = from.source.lines();
+        let (line_count, _) = lines.size_hint();
+        let last_line = lines.last().expect(Self::SOURCE_MISSING_ERROR_LOCATION);
+
+        MappedErrorLocation {
+            line_number: line_count,
+            line_column: last_line.len(),
+            source_line: last_line,
+        }
+    }
+
+    fn at_location(
+        from: &'s RHErrorWithSource<'s>,
+        location: &'s Location,
+    ) -> MappedErrorLocation<'s> {
+        MappedErrorLocation {
+            line_number: location.row,
+            line_column: location.col,
+            source_line: from
+                .source
+                .lines()
+                .nth(location.row)
+                .expect(Self::SOURCE_MISSING_ERROR_LOCATION),
+        }
+    }
+}
diff --git a/src/interpret/operator.rs b/src/interpret/operator.rs
index 42c501e..057f942 100644
--- a/src/interpret/operator.rs
+++ b/src/interpret/operator.rs
@@ -1,14 +1,13 @@
 use thiserror::Error;
 
 use crate::{
-    error::{RHError, RHErrorKind},
     parse::ast::expression::{Expression, ExpressionKind},
     types::bag::TypeBag,
 };
 
 use super::{
     value::{Value, ValueKind},
-    walker::{Walker, WalkerError},
+    walker::{Walker, WalkerError, WalkerErrorKind},
 };
 
 pub struct ValueOperator<'types> {
@@ -224,11 +223,11 @@ impl<'t> ValueOperator<'t> {
         }
     }
 
-    pub fn call(&self, val: &Value, arguments: Vec<Value>) -> Result<Value, WalkerError> {
+    pub fn call(&self, val: &Value, arguments: Vec<Value>) -> Result<Value, CallError> {
         let called = match &val.kind {
             ValueKind::Fn(i) => i,
             _ => {
-                return Err(WalkerError::OperationError(OperationError::CallableType(
+                return Err(CallError::BeforeCall(OperationError::CallableType(
                     val.clone(),
                 )))
             }
@@ -253,9 +252,10 @@ impl<'t> ValueOperator<'t> {
         let parameters = &called.node.header.parameters;
 
         if parameters.len() != arguments.len() {
-            return Err(WalkerError::OperationError(
-                OperationError::WrongArgumentCount(parameters.len(), arguments.len()),
-            ));
+            return Err(CallError::BeforeCall(OperationError::WrongArgumentCount(
+                parameters.len(),
+                arguments.len(),
+            )));
         }
 
         for (argument, parameter) in arguments.into_iter().zip(parameters.iter()) {
@@ -276,19 +276,21 @@ impl<'t> ValueOperator<'t> {
         let result = walker.walk_expression(&body_expression);
 
         match result {
-            Err(RHError {
-                kind: RHErrorKind::Run(err),
-                ..
-            }) => match err {
-                WalkerError::Return(returned_value) => Ok(returned_value),
-                _ => Err(err),
-            },
-            Err(_) => panic!("Walker returned non-walker error."),
             Ok(result) => Ok(result),
+            Err(WalkerError {
+                kind: WalkerErrorKind::Return(returned_value),
+                ..
+            }) => Ok(returned_value),
+            Err(x) => Err(CallError::InsideFunction(x)),
         }
     }
 }
 
+pub enum CallError {
+    BeforeCall(OperationError),
+    InsideFunction(WalkerError),
+}
+
 #[derive(Error, Debug)]
 pub enum OperationError {
     #[error("Can't add value '{0}' of type '{}' to value '{1}' of type '{}'.", .0.type_name(), .1.type_name())]
diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs
index 52f68c8..7c86780 100644
--- a/src/interpret/walker.rs
+++ b/src/interpret/walker.rs
@@ -1,7 +1,6 @@
 use std::{cell::RefCell, collections::HashMap, rc::Rc};
 
 use crate::{
-    error::{ErrorLocation, RHError, RHErrorKind},
     interpret::{
         operator::ValueOperator,
         value::{FnValue, ValueKind},
@@ -21,7 +20,7 @@ use crate::{
 use thiserror::Error;
 
 use super::{
-    operator::OperationError,
+    operator::{CallError, OperationError},
     scope::{ScopeChain, ScopeError},
     value::Value,
 };
@@ -44,7 +43,7 @@ impl Walker {
         Walker { scope, types }
     }
 
-    pub fn walk(&mut self, program: &Program) -> Result<(), RHError> {
+    pub fn walk(&mut self, program: &Program) -> Result<(), WalkerError> {
         self.scope.nest();
         for statement in program.statements.iter() {
             self.walk_statement(statement)?;
@@ -52,7 +51,7 @@ impl Walker {
         Ok(())
     }
 
-    fn walk_statement(&mut self, statement: &Statement) -> Result<Option<Value>, RHError> {
+    fn walk_statement(&mut self, statement: &Statement) -> Result<Option<Value>, WalkerError> {
         let result = match &statement.kind {
             StatementKind::Expression(node) => {
                 self.walk_expression(node)?;
@@ -66,9 +65,9 @@ impl Walker {
             // FIXME: Returns are always expected to have a return even though `return;` is valid.
             StatementKind::Return(node) => {
                 // If there's a function running above us it will catch this error.
-                return Err(walker_error(
+                return Err(WalkerError::new(
                     statement.at,
-                    WalkerError::Return(self.walk_expression(node)?),
+                    WalkerErrorKind::Return(self.walk_expression(node)?),
                 ));
             }
             StatementKind::Break(node) => {
@@ -78,18 +77,24 @@ impl Walker {
                     None
                 };
                 // If there's a loop above us it will catch this error.
-                return Err(walker_error(statement.at, WalkerError::LoopBreak(returned)));
+                return Err(WalkerError::new(
+                    statement.at,
+                    WalkerErrorKind::LoopBreak(returned),
+                ));
             }
             // Same here.
             StatementKind::Continue => {
-                return Err(walker_error(statement.at, WalkerError::LoopContinue));
+                return Err(WalkerError::new(
+                    statement.at,
+                    WalkerErrorKind::LoopContinue,
+                ));
             }
         };
 
         Ok(result)
     }
 
-    pub fn walk_expression(&mut self, node: &Expression) -> Result<Value, RHError> {
+    pub fn walk_expression(&mut self, node: &Expression) -> Result<Value, WalkerError> {
         match &node.kind {
             ExpressionKind::Binary { left, op, right } => {
                 // Assignment
@@ -104,7 +109,9 @@ impl Walker {
                     let left_value = self.walk_expression(left)?;
                     let is_left_true = match left_value.kind {
                         ValueKind::Bool(bool) => bool,
-                        _ => return Err(walker_error(left.at, WalkerError::WrongAndOrType)),
+                        _ => {
+                            return Err(WalkerError::new(left.at, WalkerErrorKind::WrongAndOrType))
+                        }
                     };
 
                     if let BinOp::And = op.kind {
@@ -138,7 +145,7 @@ impl Walker {
                     BinOp::Lte => exe.gte(right, left),
                     _ => unreachable!(),
                 }
-                .map_err(|err| walker_error(op.at, WalkerError::OperationError(err)))
+                .map_err(|err| WalkerError::new(op.at, WalkerErrorKind::OperationError(err)))
             }
             ExpressionKind::Unary { op, right } => {
                 let value = self.walk_expression(right)?;
@@ -149,7 +156,7 @@ impl Walker {
                     UnOp::Minus => exe.neg(value),
                     UnOp::Not => exe.not(value),
                 }
-                .map_err(|err| walker_error(op.at, WalkerError::OperationError(err)))
+                .map_err(|err| WalkerError::new(op.at, WalkerErrorKind::OperationError(err)))
             }
             ExpressionKind::Call(node) => {
                 let called = self.walk_expression(&node.called)?;
@@ -160,8 +167,15 @@ impl Walker {
                 }
 
                 let exe = ValueOperator::new(&self.types);
-                exe.call(&called, argument_values)
-                    .map_err(|err| walker_error(node.at, err))
+
+                match exe.call(&called, argument_values) {
+                    Ok(value) => Ok(value),
+                    Err(CallError::BeforeCall(op_err)) => Err(WalkerError::new(
+                        node.at,
+                        WalkerErrorKind::OperationError(op_err),
+                    )),
+                    Err(CallError::InsideFunction(err)) => Err(err),
+                }
             }
             ExpressionKind::ArrayAccess(node) => {
                 let array = self.walk_expression(&node.array)?;
@@ -169,7 +183,7 @@ impl Walker {
 
                 let exe = ValueOperator::new(&self.types);
                 exe.subscript(array, index)
-                    .map_err(|err| walker_error(node.at, WalkerError::OperationError(err)))
+                    .map_err(|err| WalkerError::new(node.at, WalkerErrorKind::OperationError(err)))
             }
             ExpressionKind::MemberAccess(_) => todo!("Structures not implemented yet."),
             ExpressionKind::Group(node) => self.walk_expression(node),
@@ -228,9 +242,9 @@ impl Walker {
                             return self.walk_block(&conditional.block);
                         }
                     } else {
-                        return Err(walker_error(
+                        return Err(WalkerError::new(
                             conditional.at,
-                            WalkerError::WrongIfConditionType,
+                            WalkerErrorKind::WrongIfConditionType,
                         ));
                     }
                 }
@@ -250,27 +264,26 @@ impl Walker {
                                 return Ok(Value::void(&self.types));
                             }
                         } else {
-                            return Err(walker_error(
+                            return Err(WalkerError::new(
                                 condition.at,
-                                WalkerError::WrongLoopConditionType,
+                                WalkerErrorKind::WrongLoopConditionType,
                             ));
                         }
                     }
 
                     match self.walk_block(&loop_node.body) {
-                        Err(RHError {
-                            kind: RHErrorKind::Run(err),
-                            at: ErrorLocation::Specific(at),
-                        }) => match err {
-                            WalkerError::LoopBreak(loop_value) => {
-                                return Ok(loop_value.unwrap_or(Value::void(&self.types)));
-                            }
-                            // Do nothing for continue and continue looping of course, you dummy.
-                            WalkerError::LoopContinue => {}
-                            // This is probably an actual error.
-                            _ => return Err(walker_error(at, err)),
-                        },
-                        Err(_) => panic!("Walker returned non-walker error."),
+                        Err(WalkerError {
+                            kind: WalkerErrorKind::LoopBreak(loop_value),
+                            ..
+                        }) => return Ok(loop_value.unwrap_or(Value::void(&self.types))),
+                        // Do nothing for continue and continue looping of course, you dummy.
+                        Err(WalkerError {
+                            kind: WalkerErrorKind::LoopContinue,
+                            ..
+                        }) => {}
+                        // This is probably an actual error.
+                        Err(x) => return Err(x),
+                        // Do nothing with values returned from loops for now.
                         _ => {}
                     }
                 }
@@ -278,11 +291,11 @@ impl Walker {
             ExpressionKind::Identifier(ident) => self
                 .scope
                 .get_var(ident, &self.types)
-                .map_err(|err| walker_error(node.at, WalkerError::ScopeError(err))),
+                .map_err(|err| WalkerError::new(node.at, WalkerErrorKind::ScopeError(err))),
         }
     }
 
-    fn walk_block(&mut self, block: &BlockExpression) -> Result<Value, RHError> {
+    fn walk_block(&mut self, block: &BlockExpression) -> Result<Value, WalkerError> {
         self.scope.nest();
 
         for statement in block.statements.iter() {
@@ -305,7 +318,7 @@ impl Walker {
         lvalue: &Expression,
         rvalue: &Expression,
         is_constant: bool,
-    ) -> Result<Value, RHError> {
+    ) -> Result<Value, WalkerError> {
         // Maybe other expressions could also be l-values, but these are fine for now.
         match &lvalue.kind {
             ExpressionKind::MemberAccess(_) => todo!("Structures not implemented yet."),
@@ -317,30 +330,37 @@ impl Walker {
                 let exe = ValueOperator::new(&self.types);
 
                 exe.subscript_assign(&mut array, index, value)
-                    .map_err(|err| walker_error(node.at, WalkerError::OperationError(err)))
+                    .map_err(|err| WalkerError::new(node.at, WalkerErrorKind::OperationError(err)))
             }
             ExpressionKind::Identifier(ident) => {
                 let value = self.walk_expression(rvalue)?;
                 self.scope
                     .set_var(ident, value.clone(), is_constant)
-                    .map_err(|err| walker_error(lvalue.at, WalkerError::ScopeError(err)))?;
+                    .map_err(|err| WalkerError::new(lvalue.at, WalkerErrorKind::ScopeError(err)))?;
                 return Ok(value);
             }
-            _ => Err(walker_error(lvalue.at, WalkerError::NonLValueAssignment)),
+            _ => Err(WalkerError::new(
+                lvalue.at,
+                WalkerErrorKind::NonLValueAssignment,
+            )),
         }
     }
 }
 
-// This assumes walker errors are always at a specific error location.
-fn walker_error(at: Location, walker_error: WalkerError) -> RHError {
-    RHError {
-        at: ErrorLocation::Specific(at),
-        kind: RHErrorKind::Run(walker_error),
+#[derive(Debug)]
+pub struct WalkerError {
+    pub kind: WalkerErrorKind,
+    pub at: Location,
+}
+
+impl WalkerError {
+    fn new(at: Location, kind: WalkerErrorKind) -> Self {
+        WalkerError { at, kind }
     }
 }
 
 #[derive(Error, Debug)]
-pub enum WalkerError {
+pub enum WalkerErrorKind {
     #[error("Loop expressions can only take boolean values as conditions.")]
     WrongLoopConditionType,
     #[error("If and Elif expressions can only take boolean values as conditions.")]
diff --git a/src/main.rs b/src/main.rs
index a670f92..d3c460c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -29,10 +29,10 @@ fn file(filename: impl AsRef<Path>) {
     let lexer = Lexer::new(&contents);
     let mut parser = Parser::new(lexer);
 
-    let node = handle_error(parser.parse(), &contents);
+    let node = handle_error(parser.parse().map_err(RHError::Parse), &contents);
     let mut walker = Walker::root();
 
-    handle_error(walker.walk(&node), &contents);
+    handle_error(walker.walk(&node).map_err(RHError::Run), &contents);
 }
 
 fn repl() {
@@ -54,8 +54,11 @@ fn repl() {
         let lexer = Lexer::new(input_buffer.trim());
         let mut parser = Parser::new(lexer);
 
-        let node = handle_error(parser.expression(), &input_buffer);
-        let result = handle_error(walker.walk_expression(&node), &input_buffer);
+        let node = handle_error(parser.expression().map_err(RHError::Parse), &input_buffer);
+        let result = handle_error(
+            walker.walk_expression(&node).map_err(RHError::Run),
+            &input_buffer,
+        );
 
         println!("🥕: {:?}\n", result);
     }
diff --git a/src/parse/macros.rs b/src/parse/macros.rs
index 9cf995c..aad6144 100644
--- a/src/parse/macros.rs
+++ b/src/parse/macros.rs
@@ -16,13 +16,13 @@ macro_rules! consume {
             if let Token {kind: $( $kind )|+, ..} = token {
                 Ok(token)
             } else {
-                Err(parser_error(ErrorLocation::Specific(token.location), ParserError::UnexpectedToken {
+                Err(ParserError::new(ParserErrorLocation::Specific(token.location), ParserErrorKind::UnexpectedToken {
                     received: token.kind,
                     expected: merge_token_names!($($kind),+),
                 }))
             }
         } else {
-            Err(parser_error(ErrorLocation::Eof, ParserError::UnexpectedEof {
+            Err(ParserError::new(ParserErrorLocation::Eof, ParserErrorKind::UnexpectedEof {
                 expected: merge_token_names!($($kind),+),
             }))
         }
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index 19f26b1..f19dcf1 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -7,8 +7,8 @@ use super::ast::nodes::{
 };
 use super::ast::statement::{Statement, StatementKind};
 use super::ast::Program;
-use crate::error::{ErrorLocation, RHError, RHErrorKind};
 use crate::lex::lexer::Lexer;
+use crate::lex::token::Location;
 use crate::lex::token::TokenKind::{self, *};
 use crate::parse::ast::nodes::{
     ArrayAccessExpression, BlockExpression, CallExpression, ConditionalBlockNode, FnExpression,
@@ -28,7 +28,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         }
     }
 
-    pub fn parse(&mut self) -> Result<Program, RHError> {
+    pub fn parse(&mut self) -> Result<Program, ParserError> {
         let mut statements = Vec::new();
 
         while !check!(self, Eof) {
@@ -38,7 +38,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(Program { statements })
     }
 
-    fn statement(&mut self) -> Result<Statement, RHError> {
+    fn statement(&mut self) -> Result<Statement, ParserError> {
         let token = self.tokens.peek().expect("Expected token.");
         match token.kind {
             KeywordPrint => self.print_statement(),
@@ -49,7 +49,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         }
     }
 
-    fn return_statement(&mut self) -> Result<Statement, RHError> {
+    fn return_statement(&mut self) -> Result<Statement, ParserError> {
         let return_token = consume!(self, KeywordReturn)?;
         let expression = self.expression()?;
         consume!(self, SemiColon)?;
@@ -59,7 +59,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn break_statement(&mut self) -> Result<Statement, RHError> {
+    fn break_statement(&mut self) -> Result<Statement, ParserError> {
         let break_token = consume!(self, KeywordBreak)?;
         let returned_on_break = if consume_if!(self, SemiColon).is_none() {
             let expression = self.expression()?;
@@ -74,7 +74,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn continue_statement(&mut self) -> Result<Statement, RHError> {
+    fn continue_statement(&mut self) -> Result<Statement, ParserError> {
         let continue_token = consume!(self, KeywordContinue)?;
         consume!(self, SemiColon)?;
         Ok(Statement {
@@ -83,7 +83,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn print_statement(&mut self) -> Result<Statement, RHError> {
+    fn print_statement(&mut self) -> Result<Statement, ParserError> {
         let print_token = consume!(self, KeywordPrint)?;
         let expression = self.expression()?;
         consume!(self, SemiColon)?;
@@ -93,7 +93,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn expression_statement(&mut self) -> Result<Statement, RHError> {
+    fn expression_statement(&mut self) -> Result<Statement, ParserError> {
         let expression = self.expression()?;
         consume!(self, SemiColon)?;
         Ok(Statement {
@@ -102,11 +102,11 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    pub fn expression(&mut self) -> Result<Expression, RHError> {
+    pub fn expression(&mut self) -> Result<Expression, ParserError> {
         self.assignment_expression()
     }
 
-    fn assignment_expression(&mut self) -> Result<Expression, RHError> {
+    fn assignment_expression(&mut self) -> Result<Expression, ParserError> {
         // Parse any expressions as l-values for now.
         let left = self.or_expression()?;
 
@@ -126,7 +126,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         }
     }
 
-    fn or_expression(&mut self) -> Result<Expression, RHError> {
+    fn or_expression(&mut self) -> Result<Expression, ParserError> {
         let mut left = self.and_expression()?;
 
         while let Some(op) = consume_if!(self, OpAnd) {
@@ -145,7 +145,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(left)
     }
 
-    fn and_expression(&mut self) -> Result<Expression, RHError> {
+    fn and_expression(&mut self) -> Result<Expression, ParserError> {
         let mut left = self.equality_expression()?;
 
         while let Some(op) = consume_if!(self, OpOr) {
@@ -164,7 +164,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(left)
     }
 
-    fn equality_expression(&mut self) -> Result<Expression, RHError> {
+    fn equality_expression(&mut self) -> Result<Expression, ParserError> {
         let mut left = self.comparison_expression()?;
 
         while let Some(op) = consume_if!(self, OpEq | OpNeq) {
@@ -183,7 +183,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(left)
     }
 
-    fn comparison_expression(&mut self) -> Result<Expression, RHError> {
+    fn comparison_expression(&mut self) -> Result<Expression, ParserError> {
         let mut left = self.term_expression()?;
 
         while let Some(op) = consume_if!(self, OpGt | OpGte | OpLt | OpLte) {
@@ -202,7 +202,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(left)
     }
 
-    fn term_expression(&mut self) -> Result<Expression, RHError> {
+    fn term_expression(&mut self) -> Result<Expression, ParserError> {
         let mut left = self.factor_expression()?;
 
         while let Some(op) = consume_if!(self, OpPlus | OpMinus) {
@@ -221,7 +221,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(left)
     }
 
-    fn factor_expression(&mut self) -> Result<Expression, RHError> {
+    fn factor_expression(&mut self) -> Result<Expression, ParserError> {
         let mut left = self.unary_expression()?;
 
         while let Some(op) = consume_if!(self, OpSlash | OpStar) {
@@ -240,7 +240,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(left)
     }
 
-    fn unary_expression(&mut self) -> Result<Expression, RHError> {
+    fn unary_expression(&mut self) -> Result<Expression, ParserError> {
         let expression = if check!(self, OpPlus | OpMinus | OpNot) {
             let op_token = self.tokens.next().unwrap();
 
@@ -258,7 +258,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(expression)
     }
 
-    fn postfix_expression(&mut self) -> Result<Expression, RHError> {
+    fn postfix_expression(&mut self) -> Result<Expression, ParserError> {
         let mut left = self.unit_expression()?;
 
         while let Some(token) = consume_if!(self, GroupOpen | ArrayOpen | Dot) {
@@ -312,7 +312,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         Ok(left)
     }
 
-    fn unit_expression(&mut self) -> Result<Expression, RHError> {
+    fn unit_expression(&mut self) -> Result<Expression, ParserError> {
         if let Some(token) = self.tokens.peek() {
             let location = token.location;
 
@@ -334,9 +334,9 @@ impl<T: Iterator<Item = Token>> Parser<T> {
                 KeywordFn => Ok(ExpressionKind::FnLiteral(Box::new(self.function()?))),
                 KeywordIf => Ok(ExpressionKind::If(Box::new(self.conditional()?))),
                 KeywordLoop => Ok(ExpressionKind::Loop(Box::new(self.repeating()?))),
-                _ => Err(parser_error(
-                    ErrorLocation::Specific(token.location),
-                    ParserError::UnexpectedToken {
+                _ => Err(ParserError::new(
+                    ParserErrorLocation::Specific(token.location),
+                    ParserErrorKind::UnexpectedToken {
                         received: token.kind.clone(),
                         expected: merge_token_names!(
                             Int(_),
@@ -359,9 +359,9 @@ impl<T: Iterator<Item = Token>> Parser<T> {
 
             Ok(Expression { at: location, kind })
         } else {
-            Err(parser_error(
-                ErrorLocation::Eof,
-                ParserError::UnexpectedEof {
+            Err(ParserError::new(
+                ParserErrorLocation::Eof,
+                ParserErrorKind::UnexpectedEof {
                     // Well sure this works.
                     expected: "expression".into(),
                 },
@@ -369,14 +369,14 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         }
     }
 
-    fn group(&mut self) -> Result<Expression, RHError> {
+    fn group(&mut self) -> Result<Expression, ParserError> {
         consume!(self, GroupOpen)?;
         let expression = self.expression()?;
         consume!(self, GroupClose)?;
         Ok(expression)
     }
 
-    fn array(&mut self) -> Result<ArrayExpression, RHError> {
+    fn array(&mut self) -> Result<ArrayExpression, ParserError> {
         let array_token = consume!(self, ArrayOpen)?;
         let mut elements = Vec::new();
 
@@ -395,7 +395,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn str(&mut self) -> Result<StrExpression, RHError> {
+    fn str(&mut self) -> Result<StrExpression, ParserError> {
         let mut parts = Vec::new();
 
         let str_token = consume!(self, StrOpen)?;
@@ -429,7 +429,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn function(&mut self) -> Result<FnExpression, RHError> {
+    fn function(&mut self) -> Result<FnExpression, ParserError> {
         let fn_token = consume!(self, KeywordFn)?;
 
         let header = {
@@ -485,7 +485,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn conditional(&mut self) -> Result<IfExpression, RHError> {
+    fn conditional(&mut self) -> Result<IfExpression, ParserError> {
         let if_token = consume!(self, KeywordIf)?;
 
         let mut conditionals = Vec::new();
@@ -524,7 +524,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn repeating(&mut self) -> Result<LoopExpression, RHError> {
+    fn repeating(&mut self) -> Result<LoopExpression, ParserError> {
         let loop_token = consume!(self, KeywordLoop)?;
 
         let condition = if consume_if!(self, KeywordIf).is_some() {
@@ -542,7 +542,7 @@ impl<T: Iterator<Item = Token>> Parser<T> {
         })
     }
 
-    fn generic_block(&mut self) -> Result<BlockExpression, RHError> {
+    fn generic_block(&mut self) -> Result<BlockExpression, ParserError> {
         let block_token = consume!(self, BlockOpen)?;
 
         let mut statements = Vec::new();
@@ -582,15 +582,26 @@ impl<T: Iterator<Item = Token>> Parser<T> {
     }
 }
 
-fn parser_error(at: ErrorLocation, parse_error: ParserError) -> RHError {
-    RHError {
-        at,
-        kind: RHErrorKind::Parse(parse_error),
+#[derive(Debug)]
+pub enum ParserErrorLocation {
+    Specific(Location),
+    Eof,
+}
+
+#[derive(Debug)]
+pub struct ParserError {
+    pub kind: ParserErrorKind,
+    pub at: ParserErrorLocation,
+}
+
+impl ParserError {
+    fn new(at: ParserErrorLocation, kind: ParserErrorKind) -> Self {
+        Self { at, kind }
     }
 }
 
 #[derive(Error, Debug)]
-pub enum ParserError {
+pub enum ParserErrorKind {
     #[error("Received unexpected '{received}', expected: {expected}.'")]
     UnexpectedToken {
         received: TokenKind,