diff --git a/forge-script-lang/src/lexer/atoms.rs b/forge-script-lang/src/lexer/atoms.rs
index 99c907b1d603f1639902f02b837612a4efbad769..0dd69b6df71e0038d145e463477a79b1a22275ab 100644
--- a/forge-script-lang/src/lexer/atoms.rs
+++ b/forge-script-lang/src/lexer/atoms.rs
@@ -1,9 +1,10 @@
 use nom::bytes::complete::tag;
-use nom::character::complete::{char, one_of};
+use nom::character::complete::{char, multispace0, multispace1, one_of};
 use nom::combinator::value;
+use nom::error::ParseError;
 use nom::multi::{many0, many1};
-use nom::sequence::terminated;
-use nom::IResult;
+use nom::sequence::{delimited, terminated};
+use nom::{Compare, IResult, InputLength, InputTake};
 use nom_locate::LocatedSpan;
 
 pub type Span<'a> = LocatedSpan<&'a str>;
@@ -33,3 +34,6 @@ pub fn raw_decimal(input: Span) -> IResult<Span, OwnedSpan> {
 		))
 	}
 }
+pub fn tag_ws<'a, 'b: 'a>(tag_val: &'b str, sp: Span<'a>) -> IResult<Span<'a>, Span<'a>> {
+	delimited(multispace0, tag(tag_val), multispace1)(sp)
+}
diff --git a/forge-script-lang/src/lexer/keywords.rs b/forge-script-lang/src/lexer/keywords.rs
index 2da25a9cc1716b34f87876c0ae46328cc3afc190..7d91ae5465fd482fa2df6cc0bdd129891c84e0e0 100644
--- a/forge-script-lang/src/lexer/keywords.rs
+++ b/forge-script-lang/src/lexer/keywords.rs
@@ -1,3 +1,4 @@
+use crate::lexer::atoms::tag_ws;
 use crate::lexer::{ScriptToken, ScriptTokenType, Span};
 use nom::bytes::complete::tag;
 use nom::IResult;
@@ -5,7 +6,7 @@ use nom_locate::position;
 
 pub fn token_struct(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("struct")(input)?;
+	let (input, _) = tag_ws("struct", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -17,7 +18,7 @@ pub fn token_struct(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_else(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("else")(input)?;
+	let (input, _) = tag_ws("else", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -29,7 +30,7 @@ pub fn token_else(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_function(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("fn")(input)?;
+	let (input, _) = tag_ws("fn", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -41,7 +42,7 @@ pub fn token_function(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_for(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("for")(input)?;
+	let (input, _) = tag_ws("for", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -53,7 +54,7 @@ pub fn token_for(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_if(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("if")(input)?;
+	let (input, _) = tag_ws("if", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -65,7 +66,7 @@ pub fn token_if(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_null(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("null")(input)?;
+	let (input, _) = tag_ws("null", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -77,7 +78,7 @@ pub fn token_null(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_print(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("print")(input)?;
+	let (input, _) = tag_ws("print", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -89,7 +90,7 @@ pub fn token_print(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_return(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("return")(input)?;
+	let (input, _) = tag_ws("return", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -101,7 +102,7 @@ pub fn token_return(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_super(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("super")(input)?;
+	let (input, _) = tag_ws("super", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -113,7 +114,7 @@ pub fn token_super(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_this(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("this")(input)?;
+	let (input, _) = tag_ws("this", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -125,7 +126,7 @@ pub fn token_this(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_let(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("let")(input)?;
+	let (input, _) = tag_ws("let", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -137,7 +138,7 @@ pub fn token_let(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_while(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("while")(input)?;
+	let (input, _) = tag_ws("while", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -149,7 +150,7 @@ pub fn token_while(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_export(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("export")(input)?;
+	let (input, _) = tag_ws("export", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -161,7 +162,7 @@ pub fn token_export(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_import(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("import")(input)?;
+	let (input, _) = tag_ws("import", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -173,7 +174,7 @@ pub fn token_import(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_alias(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("as")(input)?;
+	let (input, _) = tag_ws("as", input)?;
 	Ok((
 		input,
 		ScriptToken {
@@ -185,7 +186,7 @@ pub fn token_alias(input: Span) -> IResult<Span, ScriptToken> {
 
 pub fn token_from(input: Span) -> IResult<Span, ScriptToken> {
 	let (input, pos) = position(input)?;
-	let (input, _) = tag("from")(input)?;
+	let (input, _) = tag_ws("from", input)?;
 	Ok((
 		input,
 		ScriptToken {
diff --git a/forge-script-lang/src/lexer/mod.rs b/forge-script-lang/src/lexer/mod.rs
index 1ba895037415ed195fadc8ae779eb50e7dfbbce7..3eaf5a17bc43e30489ebefdbd3eb2fd263db56e7 100644
--- a/forge-script-lang/src/lexer/mod.rs
+++ b/forge-script-lang/src/lexer/mod.rs
@@ -6,9 +6,9 @@ mod strings;
 mod tokens;
 
 use keywords::{
-	token_alias, token_else, token_export, token_for, token_function, token_if, token_import,
-	token_let, token_null, token_print, token_return, token_struct, token_super, token_this,
-	token_while,
+	token_alias, token_else, token_export, token_for, token_from, token_function, token_if,
+	token_import, token_let, token_null, token_print, token_return, token_struct, token_super,
+	token_this, token_while,
 };
 use operators::{
 	token_asterisk, token_bang, token_bang_equal, token_caret, token_comma, token_dot,
@@ -51,6 +51,7 @@ mod _lex {
 				token_import,
 				token_struct,
 				token_super,
+				token_from,
 			)),
 			alt((
 				token_plus,
diff --git a/forge-script-lang/src/parser/grammar.rs b/forge-script-lang/src/parser/grammar.rs
index 30cbd86d5a05a3d9b0c3de6889a6aff7a2a73c78..65f96779a7b98c7375193a801e9343430a18a1ef 100644
--- a/forge-script-lang/src/parser/grammar.rs
+++ b/forge-script-lang/src/parser/grammar.rs
@@ -10,13 +10,13 @@ peg::parser! {
 			= ex:expression_list() eof() { Program(ex) }
 
 		rule expression_list() -> ExpressionList
-			= e:(statement() / expression())+ term:";"? { ExpressionList { expressions: e, is_void: term.is_some() } }
+			= e:(expression() ++ ";") term:";"? { ExpressionList { expressions: e, is_void: term.is_some() } }
 
-		rule statement() -> Expression
-			// Include conditional here separately from expression to allow "if" without semi
-			= e:conditional() { Expression::Value(ValueExpression::ConditionalBlock(e)) }
-			/ e:condition_loop() { Expression::Void(VoidExpression::ConditionLoop(e)) }
-			/ e:expression() ";" { e }
+		// rule statement() -> Expression
+		// 	Include conditional here separately from expression to allow "if" without semi
+			// = e:conditional() { Expression::Value(ValueExpression::ConditionalBlock(e)) }
+			// / e:condition_loop() { Expression::Void(VoidExpression::ConditionLoop(e)) }
+			// / e:expression() ";" { e }
 
 		pub rule expression() -> Expression
 			= ex:value_expression() { Expression::Value(ex) }
@@ -24,6 +24,9 @@ peg::parser! {
 
 		rule void_expression() -> VoidExpression
 			= ex:print() { VoidExpression::Print(ex) }
+			/ "import" "{" items:identifier_list() "}" "from" source:raw_string() { VoidExpression::Import(Import { source, items }) }
+			/ "export" "{" items:identifier_list() "}" { VoidExpression::Export(Export { items }) }
+			/ e:condition_loop() { VoidExpression::ConditionLoop(e) }
 
 		 #[cache_left_rec]
 		rule value_expression() -> ValueExpression
@@ -104,6 +107,10 @@ peg::parser! {
 			/ [ScriptToken { token_type: ScriptTokenType::Integer(vl), .. }] { LiteralNode::Number(Number::Integer(*vl)) }
 			/ [ScriptToken { token_type: ScriptTokenType::Float(vl), .. }] { LiteralNode::Number(Number::Float(*vl)) }
 
+		rule raw_string() -> String
+			= [ScriptToken { token_type: ScriptTokenType::String(vl), .. }] { String::from(*vl) }
+			/ [ScriptToken { token_type: ScriptTokenType::OwnedString(vl), .. }] { vl.clone() }
+
 		rule eof() = ![_]
 	}
 }
diff --git a/forge-script-lang/src/parser/test_suite.rs b/forge-script-lang/src/parser/test_suite.rs
index 19f8c1a75c8e05803f01dbcc40431770acbde741..52a0627a04a2e3162686fbe0d4b629a0d2b0d3ff 100644
--- a/forge-script-lang/src/parser/test_suite.rs
+++ b/forge-script-lang/src/parser/test_suite.rs
@@ -28,3 +28,24 @@ fn conditional() {
 	parse_program("if 1 + 1 { }").expect("Failed conditional with expr");
 	parse_program("if (let ident = false) { }").expect("Failed conditional with decl");
 }
+
+#[test]
+fn import_export() {
+	parse_program(r#"import { foo } from "core:runtime""#).expect("Failed import with one item");
+	parse_program(r#"import { foo, bar } from "core:runtime""#)
+		.expect("Failed import with multiple items");
+	parse_program(r#"import { foo as baz, bar } from "core:runtime""#)
+		.expect("Failed import with multiple items and alias");
+	parse_program(r#"import { foo as qwert, bar as asdf } from "core:runtime""#)
+		.expect("Failed import with multiple alias");
+	parse_program(r#"export { foo, bar }"#).expect("Failed export with multiple items");
+	parse_program(r#"export { foo as qrweas, bar }"#)
+		.expect("Failed export with multiple items and alias");
+}
+
+#[test]
+fn expression_list() {
+	parse_program("foo; bar").expect("Failed simple expression list");
+	parse_program("if flop { 123 + 2323 } else { let boo = false }; let glob = \"swarmp\"")
+		.expect("Failed simple expression list");
+}
diff --git a/src/lib.rs b/src/lib.rs
deleted file mode 100644
index 2a08c574032d8ebe42954218214cef12ee30574b..0000000000000000000000000000000000000000
--- a/src/lib.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub mod moka_script;
-mod parser;
-mod runtime;
diff --git a/src/main-web.rs b/src/main-web.rs
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index 10147288b47c3f8bbda1b291c9690a1ea4cea2b5..0000000000000000000000000000000000000000
--- a/src/main.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use micro_script::moka_script::{RunScriptError, ScriptExitCode};
-
-fn main() {
-	let mut args = std::env::args();
-	if args.len() > 2 {
-		eprintln!("Usage: mscr [script]");
-		std::process::exit(ScriptExitCode::BadCliArgs as i32);
-	} else if let Some(arg) = args.nth(1) {
-		vm_shim::run_file(arg);
-	} else {
-		vm_shim::run_repl();
-	}
-}
-
-mod vm_shim {
-	use micro_script::moka_script;
-	use micro_script::moka_script::ScriptExitCode;
-	use std::io::{BufRead, Read};
-	use std::path::PathBuf;
-
-	pub fn run_file(file_path: impl Into<PathBuf>) {
-		let file = std::fs::File::open(file_path.into());
-		if let Ok(mut file) = file {
-			let mut buff = String::new();
-			file.read_to_string(&mut buff).expect("Failed to read file");
-			if let Err(e) = moka_script::ms_run_script(buff) {
-				std::process::exit(ScriptExitCode::RunFileError as i32)
-			}
-		}
-	}
-
-	pub fn run_repl() {
-		let stdin = std::io::stdin().lock();
-		for line in stdin.lines() {
-			match line {
-				Ok(contents) => match contents.as_str() {
-					".exit" => break,
-					other => {
-						if let Err(e) = moka_script::ms_run_script(other.into()) {
-							eprintln!("{}", e);
-							std::process::exit(ScriptExitCode::BadReplError as i32);
-						}
-					}
-				},
-				Err(e) => {
-					eprintln!("Err! {}", e);
-					break;
-				}
-			}
-		}
-	}
-}
diff --git a/src/moka_script.rs b/src/moka_script.rs
deleted file mode 100644
index acb43e696cc1f2f47bbfbe400eb0e29e8eb7eb3d..0000000000000000000000000000000000000000
--- a/src/moka_script.rs
+++ /dev/null
@@ -1,103 +0,0 @@
-use crate::parser::{lex_script, parse_tokens, ScriptToken, TokenSlice};
-use std::error::Error;
-use std::fmt::{Debug, Display, Formatter};
-
-#[derive(Debug)]
-#[repr(C)]
-pub enum ScriptExitCode {
-	BadCliArgs = 64,
-	RunFileError = 65,
-	BadReplError = 66,
-}
-
-#[derive(Debug, Clone)]
-pub struct RunScriptError {
-	line: usize,
-	location: String,
-	message: String,
-}
-
-impl RunScriptError {
-	pub fn message(line: usize, message: impl ToString) -> RunScriptError {
-		RunScriptError {
-			line,
-			location: String::new(),
-			message: message.to_string(),
-		}
-	}
-
-	pub fn line(line: usize) -> RunScriptError {
-		RunScriptError {
-			line,
-			location: String::new(),
-			message: String::from("Unknown"),
-		}
-	}
-}
-
-impl Display for RunScriptError {
-	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-		write!(
-			f,
-			"[Line {}] Error {}: {}",
-			self.line, self.location, self.message
-		)
-	}
-}
-
-impl Error for RunScriptError {}
-
-pub fn ms_run_script(source: String) -> Result<(), RunScriptError> {
-	let tokens = lex_script(source.as_str()).expect("Fuck");
-	let slice = TokenSlice(tokens.as_slice());
-
-	let program = match parse_tokens(&slice) {
-		Ok(val) => val,
-		Err(e) => {
-			let (line, column) = e.get_error_location();
-
-			let previous_line = if line > 1 {
-				source.lines().nth(line - 2)
-			} else {
-				None
-			};
-			let source_line = source.lines().nth(line - 1).expect("Missing line");
-			let next_line = source.lines().nth(line);
-
-			let largest_line_num = line.max(line.saturating_sub(1)).max(line.saturating_add(1));
-			let number_length = format!("{}", largest_line_num).len();
-
-			eprintln!("| Script error on line {} at \"{}\"\n|", line, e.token);
-			if let Some(prev) = previous_line {
-				eprintln!("| [{:>width$}] {}", line - 1, prev, width = number_length);
-			}
-			eprintln!(
-				"| [{:>width$}] {}",
-				line,
-				source_line,
-				width = number_length
-			);
-			eprintln!(
-				"| {} {}{}",
-				vec![" "; number_length + 2].join(""),
-				vec![" "; column - 1].join(""),
-				vec!["^"; e.token.token_type.len()].join(""),
-			);
-			if let Some(next) = next_line {
-				eprintln!("| [{:>width$}] {}", line + 1, next, width = number_length);
-			}
-			eprintln!("|\n| Failed To Parse: {}", e.kind);
-			return Err(RunScriptError::message(line, "Failed to parse"));
-		}
-	};
-
-	#[cfg(feature = "debug-ast")]
-	{
-		println!("\n{:?}\n", tokens);
-		for expr in program.0.iter() {
-			println!("{:?}", expr);
-		}
-	}
-
-	Ok(())
-}
diff --git a/src/parser/Grammar.bnf b/src/parser/Grammar.bnf
deleted file mode 100644
index 8420aa07ff16a76ea2ba84f2c7d8f1f4bca97d2f..0000000000000000000000000000000000000000
--- a/src/parser/Grammar.bnf
+++ /dev/null
@@ -1,47 +0,0 @@
-program ::= expression_list
-block ::= "{" expression_list? "}"
-
-expression_list ::= expression (";" expression) ";"?
-
-expression ::= value_expression
-               | void_expression
-
-void_expression ::= condition_loop | import | export | block | print
-value_expression ::= unary_operator value_expression
-               | value_expression binary_operator value_expression
-               | literal
-               | conditional
-               | declare_ident
-               | assignment
-
-print ::= "print" value_expression ";"
-
-condition_loop ::= "while" value_expression block
-conditional ::= "if" value_expression block "else" conditional
-                | "if" value_expression block "else" block
-                | "if" value_expression block
-
-declare_func ::= "fn" identifier "("  ")" block
-
-declare_ident ::= "let" assignment
-                | "let" identifier
-assignment ::= identifier "=" value_expression
-export ::= "export" identifier_list
-import ::= "import" identifier_list "from" string
-identifier_list ::= "{" identifier ("as" identifier)? ("," identifier ("as" identifier)?)* "}"
-
-binary_operator ::= "*" | "/" | "+" | "-" | "%" | "^"
-                    | "&&" | "||"
-                    | "==" | "!=" | "<" | "<=" | ">" | ">="
-unary_operator ::= "-" | "!"
-identifier ::= ALPHA ALPHANUM*
-               | "_" ALPHA ALPHANUM*
-
-literal ::= integer | float | string | boolean | null
-
-boolean ::= "true" | "false"
-null ::= "null"
-string ::= '"' ANY_NON_UNESCAPED_QUOTE_TOKEN* '"'
-integer ::= "-"? DIGIT ("_"? DIGIT)*
-float ::= "-"? integer? "." integer
-          | "-"? integer "." integer?
\ No newline at end of file
diff --git a/src/parser/ast.rs b/src/parser/ast.rs
deleted file mode 100644
index fa5dfb8796584270bc9e722f30da8f3dac7ce54e..0000000000000000000000000000000000000000
--- a/src/parser/ast.rs
+++ /dev/null
@@ -1,209 +0,0 @@
-use crate::runtime::Number;
-use std::ops::Deref;
-
-pub trait AstNode {}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct Program<'a>(pub ExpressionList<'a>);
-impl<'a> AstNode for Program<'a> {}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct ExpressionList<'a> {
-	pub expressions: Vec<Expression<'a>>,
-	pub is_void: bool,
-}
-impl<'a> ExpressionList<'a> {
-	pub fn production(expressions: Vec<Expression<'a>>) -> Self {
-		ExpressionList {
-			expressions,
-			is_void: false,
-		}
-	}
-	pub fn voided(expressions: Vec<Expression<'a>>) -> Self {
-		ExpressionList {
-			expressions,
-			is_void: true,
-		}
-	}
-}
-impl<'a> Deref for ExpressionList<'a> {
-	type Target = Vec<Expression<'a>>;
-	fn deref(&self) -> &Self::Target {
-		&self.expressions
-	}
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub enum Expression<'a> {
-	Value(ValueExpression<'a>),
-	Void(VoidExpression<'a>),
-}
-
-#[derive(Copy, Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub enum UnaryOp {
-	Not,
-	Negate,
-}
-#[derive(Copy, Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub enum BinaryOp {
-	Add,
-	Subtract,
-	Multiply,
-	Divide,
-	Modulo,
-	Equals,
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub enum VoidExpression<'a> {
-	ConditionLoop(ConditionalLoop<'a>),
-	Import(Import<'a>),
-	Export(Export<'a>),
-	Print(Print<'a>),
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub enum ValueExpression<'a> {
-	Unary {
-		operator: UnaryOp,
-		operand: Box<ValueExpression<'a>>,
-	},
-	Binary {
-		lhs: Box<ValueExpression<'a>>,
-		rhs: Box<ValueExpression<'a>>,
-		operator: BinaryOp,
-	},
-	Block(ExpressionList<'a>),
-	Literal(LiteralNode<'a>),
-	DeclareIdentifier(DeclareIdent<'a>),
-	Assignment(Assignment<'a>),
-	ConditionalBlock(Conditional<'a>),
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct ConditionalLoop<'a> {
-	pub block: GuardedBlock<'a>,
-	pub fallback: Option<ExpressionList<'a>>,
-}
-
-impl<'a> ConditionalLoop<'a> {
-	pub fn expr_while(block: GuardedBlock<'a>) -> Self {
-		Self {
-			block,
-			fallback: None,
-		}
-	}
-	pub fn expr_while_else(block: GuardedBlock<'a>, fallback: ExpressionList<'a>) -> Self {
-		Self {
-			block,
-			fallback: Some(fallback),
-		}
-	}
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct Conditional<'a> {
-	pub blocks: Vec<GuardedBlock<'a>>,
-	pub fallback: Option<ExpressionList<'a>>,
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct GuardedBlock<'a> {
-	pub guard: Box<ValueExpression<'a>>,
-	pub block: ExpressionList<'a>,
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct Import<'a> {
-	pub source: &'a str,
-	pub items: IdentifierList<'a>,
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct Export<'a> {
-	pub items: IdentifierList<'a>,
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct Print<'a> {
-	pub expr: Box<ValueExpression<'a>>,
-}
-impl<'a> From<ValueExpression<'a>> for Print<'a> {
-	fn from(value: ValueExpression<'a>) -> Self {
-		Print {
-			expr: Box::new(value),
-		}
-	}
-}
-
-pub type IdentifierList<'a> = Vec<IdentifierNode<'a>>;
-pub type ParameterList<'a> = Vec<IdentifierNode<'a>>;
-
-#[derive(Copy, Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct Identifier<'a>(pub &'a str);
-
-/// Alias an identifier, to create a new way of referring to it
-/// IdentifierAlias(original, alias) => identifier "as" alias
-#[derive(Copy, Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct IdentifierAlias<'a>(pub &'a str, pub &'a str);
-
-#[derive(Copy, Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub enum IdentifierNode<'a> {
-	Direct(Identifier<'a>),
-	Alias(IdentifierAlias<'a>),
-}
-
-impl<'a> IdentifierNode<'a> {
-	pub fn get_name(&'a self) -> &'a str {
-		match self {
-			Self::Direct(value) => value.0,
-			Self::Alias(value) => value.1,
-		}
-	}
-
-	pub fn get_base(&'a self) -> &'a str {
-		match self {
-			Self::Direct(value) => value.0,
-			Self::Alias(value) => value.0,
-		}
-	}
-}
-
-#[derive(Copy, Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub enum LiteralNode<'a> {
-	Number(Number),
-	String(&'a str),
-	Boolean(bool),
-	Null,
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub struct Assignment<'a> {
-	pub ident: Identifier<'a>,
-	pub value: Box<ValueExpression<'a>>,
-}
-
-#[derive(Clone)]
-#[cfg_attr(feature = "debug-ast", derive(Debug))]
-pub enum DeclareIdent<'a> {
-	WithValue(Assignment<'a>),
-	WithoutValue(Identifier<'a>),
-}
diff --git a/src/parser/atoms.rs b/src/parser/atoms.rs
deleted file mode 100644
index 99c907b1d603f1639902f02b837612a4efbad769..0000000000000000000000000000000000000000
--- a/src/parser/atoms.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use nom::bytes::complete::tag;
-use nom::character::complete::{char, one_of};
-use nom::combinator::value;
-use nom::multi::{many0, many1};
-use nom::sequence::terminated;
-use nom::IResult;
-use nom_locate::LocatedSpan;
-
-pub type Span<'a> = LocatedSpan<&'a str>;
-pub type OwnedSpan<'a> = LocatedSpan<String>;
-
-pub fn raw_true(input: Span) -> IResult<Span, bool> {
-	value(true, tag("true"))(input)
-}
-
-pub fn raw_false(input: Span) -> IResult<Span, bool> {
-	value(false, tag("false"))(input)
-}
-
-pub fn raw_decimal(input: Span) -> IResult<Span, OwnedSpan> {
-	let input_offset = input.location_offset();
-	let input_line = input.location_line();
-
-	let (input, list) = many1(terminated(one_of("0123456789"), many0(char('_'))))(input)?;
-	let string = list.iter().fold(String::with_capacity(list.len()), |a, b| {
-		format!("{}{}", a, b)
-	});
-
-	unsafe {
-		Ok((
-			input,
-			OwnedSpan::new_from_raw_offset(input_offset, input_line, string, ()),
-		))
-	}
-}
diff --git a/src/parser/grammar.rs b/src/parser/grammar.rs
deleted file mode 100644
index 37eaf9522157794716582a76319f303b7a98ba3a..0000000000000000000000000000000000000000
--- a/src/parser/grammar.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use crate::parser::ast::Program;
-use crate::parser::{ScriptToken, ScriptTokenType};
-use peg::error::ExpectedSet;
-use peg::{Parse, ParseElem, ParseLiteral, ParseSlice, RuleResult};
-use std::error::Error;
-use std::fmt::{Display, Formatter};
-use std::ops::{Deref, DerefMut};
-
-#[derive(Clone, Debug)]
-pub enum ParseErrorKind {
-	Unexpected(ExpectedSet),
-}
-
-impl Display for ParseErrorKind {
-	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-		match self {
-			Self::Unexpected(set) => write!(f, "expected {}", set),
-		}
-	}
-}
-
-#[derive(Clone, Debug)]
-pub struct ParseError<'a> {
-	pub token: &'a ScriptToken<'a>,
-	pub kind: ParseErrorKind,
-}
-impl<'a> ParseError<'a> {
-	pub fn get_error_location(&self) -> (usize, usize) {
-		(
-			self.token.position.location_line() as usize,
-			self.token.position.get_column(),
-		)
-	}
-}
-impl<'a> Display for ParseError<'a> {
-	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-		write!(
-			f,
-			"Failed to parse at [{}, {}]: {}. {}",
-			self.token.position.location_line(),
-			self.token.position.get_column(),
-			self.token.position.fragment(),
-			self.kind,
-		)
-	}
-}
-
-impl<'a> Error for ParseError<'a> {}
-
-pub fn parse_tokens<'a>(list: &'a TokenSlice) -> Result<Program<'a>, ParseError<'a>> {
-	match script_parser::program(list) {
-		Ok(prog) => Ok(prog),
-		Err(e) => {
-			let bad_token = &list[e.location];
-			Err(ParseError {
-				token: bad_token,
-				kind: ParseErrorKind::Unexpected(e.expected),
-			})
-		}
-	}
-}
diff --git a/src/parser/keywords.rs b/src/parser/keywords.rs
deleted file mode 100644
index 2a57ca39a74377bd06855f7f32bac8df66240614..0000000000000000000000000000000000000000
--- a/src/parser/keywords.rs
+++ /dev/null
@@ -1,197 +0,0 @@
-use crate::parser::atoms::Span;
-use crate::parser::{ScriptToken, ScriptTokenType};
-use nom::bytes::complete::tag;
-use nom::IResult;
-use nom_locate::position;
-
-pub fn token_struct(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("struct")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Class,
-		},
-	))
-}
-
-pub fn token_else(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("else")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Else,
-		},
-	))
-}
-
-pub fn token_function(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("fn")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Function,
-		},
-	))
-}
-
-pub fn token_for(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("for")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::For,
-		},
-	))
-}
-
-pub fn token_if(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("if")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::If,
-		},
-	))
-}
-
-pub fn token_null(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("null")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Null,
-		},
-	))
-}
-
-pub fn token_print(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("print")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Print,
-		},
-	))
-}
-
-pub fn token_return(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("return")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Return,
-		},
-	))
-}
-
-pub fn token_super(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("super")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Super,
-		},
-	))
-}
-
-pub fn token_this(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("this")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::This,
-		},
-	))
-}
-
-pub fn token_let(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("let")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Let,
-		},
-	))
-}
-
-pub fn token_while(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("while")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::While,
-		},
-	))
-}
-
-pub fn token_export(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("export")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Export,
-		},
-	))
-}
-
-pub fn token_import(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("import")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Import,
-		},
-	))
-}
-
-pub fn token_alias(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("as")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Alias,
-		},
-	))
-}
-
-pub fn token_from(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("from")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::From,
-		},
-	))
-}
diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs
deleted file mode 100644
index 8aa24c305247bc9f2c17b1c6798bc527fa96aacc..0000000000000000000000000000000000000000
--- a/src/parser/lexer.rs
+++ /dev/null
@@ -1,171 +0,0 @@
-use crate::parser::atoms::Span;
-use crate::parser::ScriptToken;
-use nom::branch::alt;
-use nom::character::complete::multispace0;
-use nom::error::ErrorKind;
-use nom::multi::fold_many0;
-use nom::sequence::delimited;
-use nom::IResult;
-use nom_locate::LocatedSpan;
-use std::error::Error;
-use std::fmt::{Display, Formatter};
-
-use crate::parser::token_parser::{
-	token_alias, token_asterisk, token_bang, token_bang_equal, token_boolean, token_caret,
-	token_comma, token_dot, token_double_ampersand, token_double_pipe, token_else, token_equal,
-	token_equal_equal, token_export, token_float, token_for, token_function, token_greater,
-	token_greater_equal, token_ident, token_if, token_import, token_int, token_left_brace,
-	token_left_paren, token_less, token_less_equal, token_let, token_minus, token_modulo,
-	token_null, token_plus, token_print, token_return, token_right_brace, token_right_paren,
-	token_semicolon, token_slash, token_string, token_struct, token_super, token_this, token_while,
-};
-
-pub fn any_token(input: Span) -> IResult<Span, ScriptToken> {
-	alt((
-		alt((
-			token_if,
-			token_function,
-			token_alias,
-			token_for,
-			token_let,
-			token_else,
-			token_this,
-			token_null,
-			token_while,
-			token_return,
-			token_print,
-			token_export,
-			token_import,
-			token_struct,
-			token_super,
-		)),
-		alt((
-			token_plus,
-			token_minus,
-			token_asterisk,
-			token_slash,
-			token_bang,
-			token_comma,
-			token_dot,
-			token_caret,
-			token_modulo,
-			token_left_brace,
-			token_left_paren,
-			token_right_brace,
-			token_right_paren,
-			token_double_ampersand,
-			token_double_pipe,
-			token_semicolon,
-		)),
-		alt((
-			token_less,
-			token_greater,
-			token_equal,
-			token_equal_equal,
-			token_bang_equal,
-			token_less_equal,
-			token_greater_equal,
-		)),
-		alt((
-			token_float,
-			token_int,
-			token_boolean,
-			token_string,
-			token_ident,
-		)),
-	))(input)
-}
-
-pub fn token_list(input: Span) -> IResult<Span, Vec<ScriptToken>> {
-	let (span, list) = fold_many0(
-		delimited(multispace0, any_token, multispace0),
-		Vec::new,
-		|mut list, tok| {
-			list.push(tok);
-			list
-		},
-	)(input)?;
-
-	Ok((span, list))
-}
-
-#[derive(Debug)]
-pub struct LexError<'a> {
-	pub inner: nom::error::Error<Span<'a>>,
-}
-
-impl<'a> LexError<'a> {
-	pub fn get_error_location(&self) -> (usize, usize) {
-		(
-			self.inner.input.location_line() as usize,
-			self.inner.input.get_column(),
-		)
-	}
-}
-impl<'a> Display for LexError<'a> {
-	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-		write!(f, "{}", self.inner)
-	}
-}
-impl<'a> Error for LexError<'a> {}
-impl<'a> From<nom::Err<nom::error::Error<Span<'a>>>> for LexError<'a> {
-	fn from(value: nom::Err<nom::error::Error<Span<'a>>>) -> Self {
-		match value {
-			nom::Err::Error(err) => Self { inner: err },
-			nom::Err::Failure(err) => Self { inner: err },
-			nom::Err::Incomplete(_) => Self {
-				inner: nom::error::Error::new(
-					LocatedSpan::new("<incomplete program>"),
-					ErrorKind::Alt,
-				),
-			},
-		}
-	}
-}
-
-pub fn lex_script<'a, 'b: 'a>(script: &'b str) -> Result<Vec<ScriptToken<'a>>, LexError> {
-	let script_span = Span::new(script);
-	let tokens = token_list(script_span).map_err(LexError::from)?;
-	Ok(tokens.1)
-}
-
-#[cfg(test)]
-mod lexing_test {
-	use crate::parser::lexer::lex_script;
-	use crate::parser::{ScriptToken, ScriptTokenType};
-
-	#[test]
-	fn simple_maths() {
-		let tokens = lex_script("12 + 21").expect("Failed to lex");
-
-		assert_eq!(tokens.len(), 3);
-		assert_eq!(tokens[0].token_type, ScriptTokenType::Integer(12));
-		assert_eq!(tokens[1].token_type, ScriptTokenType::Plus);
-		assert_eq!(tokens[2].token_type, ScriptTokenType::Integer(21));
-	}
-	#[test]
-	fn multiline() {
-		let script = r#"
-		"Foo"; "Bar";
-		12 + 21
-		"#;
-
-		let tokens = lex_script(script).expect("Failed to lex");
-		assert_eq!(tokens.len(), 7);
-
-		assert_eq!(
-			tokens[0].token_type,
-			ScriptTokenType::OwnedString(String::from("Foo"))
-		);
-		assert_eq!(tokens[1].token_type, ScriptTokenType::Semicolon);
-		assert_eq!(
-			tokens[2].token_type,
-			ScriptTokenType::OwnedString(String::from("Bar"))
-		);
-		assert_eq!(tokens[3].token_type, ScriptTokenType::Semicolon);
-
-		assert_eq!(tokens[4].token_type, ScriptTokenType::Integer(12));
-		assert_eq!(tokens[5].token_type, ScriptTokenType::Plus);
-		assert_eq!(tokens[6].token_type, ScriptTokenType::Integer(21));
-	}
-}
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
deleted file mode 100644
index 6f585af9e06c6309fe4ce5cea750799d2dea3935..0000000000000000000000000000000000000000
--- a/src/parser/mod.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-mod ast;
-mod atoms;
-mod grammar;
-mod keywords;
-mod lexer;
-mod operators;
-mod primitives;
-mod strings;
-mod tokens;
-
-pub mod token_parser {
-	pub use super::keywords::{
-		token_alias, token_else, token_export, token_for, token_function, token_if, token_import,
-		token_let, token_null, token_print, token_return, token_struct, token_super, token_this,
-		token_while,
-	};
-	pub use super::operators::{
-		token_asterisk, token_bang, token_bang_equal, token_caret, token_comma, token_dot,
-		token_double_ampersand, token_double_pipe, token_equal, token_equal_equal, token_greater,
-		token_greater_equal, token_left_brace, token_left_paren, token_less, token_less_equal,
-		token_minus, token_modulo, token_plus, token_right_brace, token_right_paren,
-		token_semicolon, token_slash,
-	};
-	pub use super::primitives::{token_boolean, token_float, token_ident, token_int};
-	pub use super::strings::token_string;
-}
-pub use grammar::{parse_tokens, TokenSlice};
-pub use lexer::lex_script;
-pub use tokens::{ScriptToken, ScriptTokenType};
-
-#[cfg(test)]
-#[macro_export]
-macro_rules! map_result {
-	($val: expr, $with: expr) => {
-		match $val {
-			Ok((remainder, token)) => $with(remainder, token),
-			Err(nom::Err::Incomplete(_)) => panic!("Incorrect error type"),
-			Err(nom::Err::Failure(err)) | Err(nom::Err::Error(err)) => {
-				panic!(
-					"At [{}:{}]: {}; Value ||{}||",
-					&err.input.location_line(),
-					&err.input.get_column(),
-					&err.code.description(),
-					&err.input
-				);
-			}
-		}
-	};
-	($val: expr, $with: expr, $printable: expr) => {
-		match $val {
-			Ok((remainder, token)) => $with(remainder, token),
-			Err(nom::Err::Incomplete(_)) => panic!("Incorrect error type"),
-			Err(nom::Err::Failure(err)) | Err(nom::Err::Error(err)) => {
-				panic!(
-					"At [{}:{}]: {}; Value {}",
-					&err.input.location_line(),
-					&err.input.get_column(),
-					&err.code.description(),
-					$printable
-				);
-			}
-		}
-	};
-}
diff --git a/src/parser/operators.rs b/src/parser/operators.rs
deleted file mode 100644
index 3f8f51abf72170e72ec6136c993fa678e1ba9014..0000000000000000000000000000000000000000
--- a/src/parser/operators.rs
+++ /dev/null
@@ -1,326 +0,0 @@
-use crate::parser::atoms::Span;
-use crate::parser::{ScriptToken, ScriptTokenType};
-use nom::bytes::complete::tag;
-use nom::IResult;
-use nom_locate::position;
-
-pub fn token_left_paren(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("(")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::LeftParen,
-		},
-	))
-}
-
-pub fn token_right_paren(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag(")")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::RightParen,
-		},
-	))
-}
-
-pub fn token_left_brace(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("{")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::LeftBrace,
-		},
-	))
-}
-
-pub fn token_right_brace(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("}")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::RightBrace,
-		},
-	))
-}
-
-pub fn token_comma(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag(",")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Comma,
-		},
-	))
-}
-
-pub fn token_dot(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag(".")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Dot,
-		},
-	))
-}
-
-pub fn token_minus(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("-")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Minus,
-		},
-	))
-}
-
-pub fn token_plus(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("+")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Plus,
-		},
-	))
-}
-
-pub fn token_semicolon(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag(";")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Semicolon,
-		},
-	))
-}
-
-pub fn token_slash(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("/")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Slash,
-		},
-	))
-}
-
-pub fn token_asterisk(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("*")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Asterisk,
-		},
-	))
-}
-
-pub fn token_bang(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("!")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Bang,
-		},
-	))
-}
-
-pub fn token_bang_equal(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("!=")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::BangEqual,
-		},
-	))
-}
-
-pub fn token_equal(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("=")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Equal,
-		},
-	))
-}
-
-pub fn token_equal_equal(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("==")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::EqualEqual,
-		},
-	))
-}
-
-pub fn token_greater(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag(">")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Greater,
-		},
-	))
-}
-
-pub fn token_greater_equal(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag(">=")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::GreaterEqual,
-		},
-	))
-}
-
-pub fn token_less(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("<")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Less,
-		},
-	))
-}
-
-pub fn token_less_equal(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("<=")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::LessEqual,
-		},
-	))
-}
-
-pub fn token_double_pipe(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("||")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::DoublePipe,
-		},
-	))
-}
-
-pub fn token_double_ampersand(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("&&")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::DoubleAmpersand,
-		},
-	))
-}
-
-pub fn token_modulo(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("%")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Modulo,
-		},
-	))
-}
-
-pub fn token_caret(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, _) = tag("^")(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Caret,
-		},
-	))
-}
-
-#[cfg(test)]
-mod operator_checks {
-	use super::*;
-	use crate::parser::atoms::Span;
-
-	fn s(st: &str) -> Span {
-		Span::new(st)
-	}
-
-	#[test]
-	fn parse_brackets() {
-		assert_eq!(
-			token_left_brace(s("{"))
-				.expect("Failed to parse")
-				.1
-				.token_type,
-			ScriptTokenType::LeftBrace
-		);
-
-		assert_eq!(
-			token_right_brace(s("}"))
-				.expect("Failed to parse")
-				.1
-				.token_type,
-			ScriptTokenType::RightBrace
-		);
-
-		assert_eq!(
-			token_left_paren(s("("))
-				.expect("Failed to parse")
-				.1
-				.token_type,
-			ScriptTokenType::LeftParen
-		);
-
-		assert_eq!(
-			token_right_paren(s(")"))
-				.expect("Failed to parse")
-				.1
-				.token_type,
-			ScriptTokenType::RightParen
-		);
-	}
-}
diff --git a/src/parser/primitives.rs b/src/parser/primitives.rs
deleted file mode 100644
index 068644aefc9b6307f4a862e7781d3bc017628dfa..0000000000000000000000000000000000000000
--- a/src/parser/primitives.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-use crate::parser::atoms::{raw_decimal, raw_false, raw_true, Span};
-use crate::parser::tokens::{ScriptToken, ScriptTokenType};
-use nom::branch::alt;
-use nom::bytes::complete::{escaped, is_not, tag};
-use nom::character::complete::{alpha1, alphanumeric1, char, one_of};
-use nom::combinator::{opt, recognize};
-use nom::multi::many0_count;
-use nom::sequence::{delimited, pair, separated_pair};
-use nom::{error_position, IResult};
-use nom_locate::position;
-
-pub fn token_ident(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, value) = recognize(pair(
-		alt((alpha1, tag("_"))),
-		many0_count(alt((alphanumeric1, tag("_")))),
-	))(input)?;
-
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Identifier(value.fragment()),
-		},
-	))
-}
-
-pub fn token_int(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, sign) = opt(one_of("+-"))(input)?;
-	let (input, value) = raw_decimal(input)?;
-
-	format!("{}{}", sign.map(String::from).unwrap_or_default(), value)
-		.parse::<i64>()
-		.map(|value| {
-			(
-				input,
-				ScriptToken {
-					token_type: ScriptTokenType::Integer(value),
-					position: pos,
-				},
-			)
-		})
-		.map_err(|_| nom::Err::Failure(error_position!(pos, nom::error::ErrorKind::Digit)))
-}
-
-pub fn token_float(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, sign) = opt(one_of("+-"))(input)?;
-	let (input, (before, after)) =
-		separated_pair(opt(raw_decimal), tag("."), opt(raw_decimal))(input)?;
-
-	let formatted_number = format!(
-		"{}{}.{}",
-		sign.map(String::from).unwrap_or_default(),
-		before
-			.map(|s| s.fragment().to_owned())
-			.unwrap_or_else(|| String::from("0")),
-		after
-			.map(|s| s.fragment().to_owned())
-			.unwrap_or_else(|| String::from("0"))
-	);
-
-	formatted_number
-		.parse::<f64>()
-		.map(|value| {
-			(
-				input,
-				ScriptToken {
-					token_type: ScriptTokenType::Float(value),
-					position: pos,
-				},
-			)
-		})
-		.map_err(|_| nom::Err::Failure(error_position!(pos, nom::error::ErrorKind::Digit)))
-}
-
-pub fn token_boolean(input: Span) -> IResult<Span, ScriptToken> {
-	let (input, pos) = position(input)?;
-	let (input, value) = alt((raw_true, raw_false))(input)?;
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::Boolean(value),
-		},
-	))
-}
-
-#[cfg(test)]
-mod parsing_tests {
-	use super::*;
-	use crate::map_result;
-
-	#[test]
-	fn parse_integer() {
-		let positive_cases = [
-			("1234", 1234),
-			("-1234", -1234),
-			("0", 0),
-			("1_000_000", 1000000),
-			("-12_34", -1234),
-		];
-
-		for (program, expected) in positive_cases {
-			map_result!(token_int(Span::new(program)), |_, token: ScriptToken| {
-				assert_eq!(token.token_type, ScriptTokenType::Integer(expected))
-			});
-		}
-	}
-	#[test]
-	fn parse_floats() {
-		let positive_cases = [
-			("12.34", 12.34),
-			("-12.34", -12.34),
-			("0.", 0.),
-			(".0", 0.),
-			(".0.", 0.),
-			(".0.1.2", 0.),
-			("1_000_000.1_23", 1000000.123),
-			("-12_34.0_0_0", -1234.0),
-		];
-
-		for (program, expected) in positive_cases {
-			map_result!(token_float(Span::new(program)), |_, token: ScriptToken| {
-				assert_eq!(token.token_type, ScriptTokenType::Float(expected))
-			});
-		}
-	}
-
-	#[test]
-	fn parse_bools() {
-		let positive_cases = [("true", true), ("false", false)];
-
-		for (program, expected) in positive_cases {
-			map_result!(
-				token_boolean(Span::new(program)),
-				|_, token: ScriptToken| {
-					assert_eq!(token.token_type, ScriptTokenType::Boolean(expected))
-				}
-			);
-		}
-	}
-
-	#[test]
-	fn parse_identifier() {
-		let positive_cases = ["BarBaz", "Foo", "foo", "foasd123", "_adad"];
-
-		for expected in positive_cases {
-			map_result!(token_ident(Span::new(expected)), |_, token: ScriptToken| {
-				assert_eq!(token.token_type, ScriptTokenType::Identifier(expected))
-			});
-		}
-	}
-}
diff --git a/src/parser/strings.rs b/src/parser/strings.rs
deleted file mode 100644
index a83756cfce61e2bd064ff67719e72b6d45ce95b3..0000000000000000000000000000000000000000
--- a/src/parser/strings.rs
+++ /dev/null
@@ -1,193 +0,0 @@
-// parser combinators are constructed from the bottom up:
-// first we write parsers for the smallest elements (escaped characters),
-// then combine them into larger parsers.
-
-use crate::parser::atoms::Span;
-use crate::parser::{ScriptToken, ScriptTokenType};
-use nom::branch::alt;
-use nom::bytes::complete::{is_not, take_while_m_n};
-use nom::character::complete::{char as p_char, multispace1, one_of};
-use nom::combinator::{map, map_opt, map_res, value, verify};
-use nom::multi::fold_many1;
-use nom::sequence::{delimited, preceded};
-use nom::IResult;
-use nom_locate::position;
-
-/// Parse a unicode sequence, of the form u{XXXX}, where XXXX is 1 to 6
-/// hexadecimal numerals. We will combine this later with parse_escaped_char
-/// to parse sequences like \u{00AC}.
-fn parse_unicode(input: Span) -> IResult<Span, char> {
-	// `take_while_m_n` parses between `m` and `n` bytes (inclusive) that match
-	// a predicate. `parse_hex` here parses between 1 and 6 hexadecimal numerals.
-	let parse_hex = take_while_m_n(1, 6, |ch: char| ch.is_ascii_hexdigit());
-
-	// `preceded` takes a prefix parser, and if it succeeds, returns the result
-	// of the body parser. In this case, it parses u{XXXX}.
-	let parse_delimited_hex = preceded(
-		p_char::<Span, nom::error::Error<Span>>('u'),
-		// `delimited` is like `preceded`, but it parses both a prefix and a suffix.
-		// It returns the result of the middle parser. In this case, it parses
-		// {XXXX}, where XXXX is 1 to 6 hex numerals, and returns XXXX
-		delimited(p_char('{'), parse_hex, p_char('}')),
-	);
-
-	// `map_res` takes the result of a parser and applies a function that returns
-	// a Result. In this case we take the hex bytes from parse_hex and attempt to
-	// convert them to a u32.
-	let parse_u32 = map_res(parse_delimited_hex, move |hex| {
-		u32::from_str_radix(hex.fragment(), 16)
-	});
-
-	// map_opt is like map_res, but it takes an Option instead of a Result. If
-	// the function returns None, map_opt returns an error. In this case, because
-	// not all u32 values are valid unicode code points, we have to fallibly
-	// convert to p_char with from_u32.
-	let (span, char) = map_opt(parse_u32, move |val| char::from_u32(val))(input)?;
-	Ok((span, char))
-}
-
-/// Parse an escaped character: \n, \t, \r, \u{00AC}, etc.
-fn parse_escaped_char(input: Span) -> IResult<Span, char> {
-	preceded(
-		p_char('\\'),
-		// `alt` tries each parser in sequence, returning the result of
-		// the first successful match
-		alt((
-			parse_unicode,
-			// The `value` parser returns a fixed value (the first argument) if its
-			// parser (the second argument) succeeds. In these cases, it looks for
-			// the marker characters (n, r, t, etc) and returns the matching
-			// character (\n, \r, \t, etc).
-			value('\n', p_char('n')),
-			value('\r', p_char('r')),
-			value('\t', p_char('t')),
-			value('\u{08}', p_char('b')),
-			value('\u{0C}', p_char('f')),
-			value('\\', p_char('\\')),
-			value('/', p_char('/')),
-			value('"', p_char('"')),
-		)),
-	)(input)
-}
-
-/// Parse a backslash, followed by any amount of whitespace. This is used later
-/// to discard any escaped whitespace.
-fn parse_escaped_whitespace(input: Span) -> IResult<Span, Span> {
-	preceded(p_char('\\'), multispace1)(input)
-}
-
-/// Parse a non-empty block of text that doesn't include \ or "
-fn parse_literal(input: Span) -> IResult<Span, Span> {
-	// `is_not` parses a string of 0 or more characters that aren't one of the
-	// given characters.
-	let not_quote_slash = is_not("\"\\");
-
-	// `verify` runs a parser, then runs a verification function on the output of
-	// the parser. The verification function accepts out output only if it
-	// returns true. In this case, we want to ensure that the output of is_not
-	// is non-empty.
-	verify(not_quote_slash, |s: &Span| !s.fragment().is_empty())(input)
-}
-
-/// A string fragment contains a fragment of a string being parsed: either
-/// a non-empty Literal (a series of non-escaped characters), a single
-/// parsed escaped character, or a block of escaped whitespace.
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-enum StringFragment<'a> {
-	Literal(&'a str),
-	EscapedChar(char),
-	EscapedWS,
-}
-
-/// Combine parse_literal, parse_escaped_whitespace, and parse_escaped_char
-/// into a StringFragment.
-fn parse_fragment(input: Span) -> IResult<Span, StringFragment> {
-	alt((
-		map(parse_literal, |sp: Span| {
-			StringFragment::Literal(sp.fragment())
-		}),
-		map(parse_escaped_char, StringFragment::EscapedChar),
-		value(StringFragment::EscapedWS, parse_escaped_whitespace),
-	))(input)
-}
-
-/// Parse a string. Use a loop of parse_fragment and push all of the fragments
-/// into an output string.
-pub fn token_string(input: Span) -> IResult<Span, ScriptToken> {
-	// fold is the equivalent of iterator::fold. It runs a parser in a loop,
-	// and for each output value, calls a folding function on each output value.
-	let build_string = fold_many1(
-		// Our parser function– parses a single string fragment
-		parse_fragment,
-		// Our init value, an empty string
-		String::new,
-		// Our folding function. For each fragment, append the fragment to the
-		// string.
-		|mut string, fragment| {
-			match fragment {
-				StringFragment::Literal(s) => string.push_str(s),
-				StringFragment::EscapedChar(c) => string.push(c),
-				StringFragment::EscapedWS => {}
-			}
-			string
-		},
-	);
-
-	let (input, pos) = position(input)?;
-	let (input, value) = delimited(p_char('"'), build_string, p_char('"'))(input)?;
-
-	Ok((
-		input,
-		ScriptToken {
-			position: pos,
-			token_type: ScriptTokenType::OwnedString(value),
-		},
-	))
-}
-
-#[cfg(test)]
-mod string_test {
-	use super::token_string;
-	use crate::map_result;
-	use crate::parser::atoms::Span;
-	use crate::parser::{ScriptToken, ScriptTokenType};
-
-	#[test]
-	fn parse_escaped_string() {
-		let positive_cases = [
-			(
-				r#""This is an escaped String""#,
-				String::from("This is an escaped String"),
-			),
-			(
-				r#""This is an \"escaped\" String""#,
-				String::from("This is an \"escaped\" String"),
-			),
-			(
-				r#""Many whitespaces can be collapsed with a slash \
-				and they won't matter""#,
-				String::from(
-					"Many whitespaces can be collapsed with a slash and they won't matter",
-				),
-			),
-			(
-				r#""Big whitespace preserved can be collapsed with a slash
-				and they won't matter""#,
-				String::from(
-					r#"Big whitespace preserved can be collapsed with a slash
-				and they won't matter"#,
-				),
-			),
-		];
-
-		for (program, expected) in positive_cases {
-			map_result!(
-				token_string(Span::new(program)),
-				|_, token: ScriptToken| {
-					assert_eq!(token.token_type, ScriptTokenType::OwnedString(expected))
-				},
-				program
-			);
-		}
-	}
-}
diff --git a/src/parser/tokens.rs b/src/parser/tokens.rs
deleted file mode 100644
index 6b3499546db819fed60b4110b01bfd43bd3bcfb7..0000000000000000000000000000000000000000
--- a/src/parser/tokens.rs
+++ /dev/null
@@ -1,368 +0,0 @@
-use crate::parser::atoms::Span;
-use std::error::Error;
-use std::fmt::{format, Debug, Display, Formatter};
-
-#[derive(PartialEq, Clone, Debug)]
-pub enum ScriptTokenType<'a> {
-	// Structural Tokens
-	LeftParen,
-	RightParen,
-	LeftBrace,
-	RightBrace,
-	Comma,
-	Dot,
-	Semicolon,
-
-	// Unary Operators
-	Bang,
-	Minus,
-
-	// Binary Operators
-	Asterisk,
-	Slash,
-	Plus,
-	BangEqual,
-	Equal,
-	EqualEqual,
-	Greater,
-	GreaterEqual,
-	Less,
-	LessEqual,
-	DoublePipe,
-	DoubleAmpersand,
-	Modulo,
-	Caret,
-
-	// Literals
-	Identifier(&'a str),
-	String(&'a str),
-	OwnedString(String),
-	Integer(i64),
-	Float(f64),
-	Boolean(bool),
-
-	// Keywords
-	Class,
-	Else,
-	Function,
-	For,
-	If,
-	Null,
-	Print,
-	Return,
-	Super,
-	This,
-	Let,
-	While,
-	Export,
-	Import,
-	Alias,
-	From,
-
-	// Misc
-	Eof,
-}
-
-impl<'a> ScriptTokenType<'a> {
-	pub fn len(&self) -> usize {
-		match self {
-			ScriptTokenType::LeftParen => 1,
-			ScriptTokenType::RightParen => 1,
-			ScriptTokenType::LeftBrace => 2,
-			ScriptTokenType::RightBrace => 2,
-			ScriptTokenType::Comma => 1,
-			ScriptTokenType::Dot => 1,
-			ScriptTokenType::Minus => 1,
-			ScriptTokenType::Plus => 1,
-			ScriptTokenType::Semicolon => 1,
-			ScriptTokenType::Slash => 1,
-			ScriptTokenType::Asterisk => 1,
-			ScriptTokenType::Bang => 1,
-			ScriptTokenType::BangEqual => 2,
-			ScriptTokenType::Equal => 1,
-			ScriptTokenType::EqualEqual => 2,
-			ScriptTokenType::Greater => 1,
-			ScriptTokenType::GreaterEqual => 2,
-			ScriptTokenType::Less => 1,
-			ScriptTokenType::LessEqual => 2,
-			ScriptTokenType::DoublePipe => 2,
-			ScriptTokenType::DoubleAmpersand => 2,
-			ScriptTokenType::Modulo => 1,
-			ScriptTokenType::Caret => 1,
-			ScriptTokenType::Identifier(value) => value.len(),
-			ScriptTokenType::String(value) => value.len() + 2,
-			ScriptTokenType::OwnedString(value) => value.len() + 2,
-			ScriptTokenType::Integer(value) => format!("{}", value).len(),
-			ScriptTokenType::Float(value) => format!("{}", value).len(),
-			ScriptTokenType::Boolean(value) => {
-				if *value {
-					4
-				} else {
-					5
-				}
-			}
-			ScriptTokenType::Class => 6,
-			ScriptTokenType::Else => 4,
-			ScriptTokenType::Function => 2,
-			ScriptTokenType::For => 3,
-			ScriptTokenType::If => 2,
-			ScriptTokenType::Null => 4,
-			ScriptTokenType::Print => 5,
-			ScriptTokenType::Return => 6,
-			ScriptTokenType::Super => 5,
-			ScriptTokenType::This => 4,
-			ScriptTokenType::Let => 3,
-			ScriptTokenType::While => 5,
-			ScriptTokenType::Export => 6,
-			ScriptTokenType::Import => 6,
-			ScriptTokenType::Alias => 2,
-			ScriptTokenType::From => 4,
-			ScriptTokenType::Eof => 0,
-		}
-	}
-}
-
-impl<'a> Display for ScriptTokenType<'a> {
-	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-		match self {
-			ScriptTokenType::LeftParen => write!(f, "("),
-			ScriptTokenType::RightParen => write!(f, ")"),
-			ScriptTokenType::LeftBrace => write!(f, "{{"),
-			ScriptTokenType::RightBrace => write!(f, "}}"),
-			ScriptTokenType::Comma => write!(f, ","),
-			ScriptTokenType::Dot => write!(f, "."),
-			ScriptTokenType::Minus => write!(f, "-"),
-			ScriptTokenType::Plus => write!(f, "+"),
-			ScriptTokenType::Semicolon => write!(f, ";"),
-			ScriptTokenType::Slash => write!(f, "/"),
-			ScriptTokenType::Asterisk => write!(f, "*"),
-			ScriptTokenType::Bang => write!(f, "!"),
-			ScriptTokenType::BangEqual => write!(f, "!="),
-			ScriptTokenType::Equal => write!(f, "="),
-			ScriptTokenType::EqualEqual => write!(f, "=="),
-			ScriptTokenType::Greater => write!(f, ">"),
-			ScriptTokenType::GreaterEqual => write!(f, ">="),
-			ScriptTokenType::Less => write!(f, "<"),
-			ScriptTokenType::LessEqual => write!(f, "<="),
-			ScriptTokenType::DoublePipe => write!(f, "||"),
-			ScriptTokenType::DoubleAmpersand => write!(f, "&&"),
-			ScriptTokenType::Modulo => write!(f, "%"),
-			ScriptTokenType::Caret => write!(f, "^"),
-			ScriptTokenType::Identifier(value) => write!(f, "{}", value),
-			ScriptTokenType::String(value) => write!(f, "{}", value),
-			ScriptTokenType::OwnedString(value) => write!(f, "{}", value),
-			ScriptTokenType::Integer(value) => write!(f, "{}", value),
-			ScriptTokenType::Float(value) => write!(f, "{}", value),
-			ScriptTokenType::Boolean(value) => write!(f, "{}", value),
-			ScriptTokenType::Class => write!(f, "struct"),
-			ScriptTokenType::Else => write!(f, "else"),
-			ScriptTokenType::Function => write!(f, "fn"),
-			ScriptTokenType::For => write!(f, "for"),
-			ScriptTokenType::If => write!(f, "if"),
-			ScriptTokenType::Null => write!(f, "null"),
-			ScriptTokenType::Print => write!(f, "print"),
-			ScriptTokenType::Return => write!(f, "return"),
-			ScriptTokenType::Super => write!(f, "super"),
-			ScriptTokenType::This => write!(f, "this"),
-			ScriptTokenType::Let => write!(f, "let"),
-			ScriptTokenType::While => write!(f, "while"),
-			ScriptTokenType::Export => write!(f, "export"),
-			ScriptTokenType::Import => write!(f, "import"),
-			ScriptTokenType::Alias => write!(f, "as"),
-			ScriptTokenType::From => write!(f, "from"),
-			ScriptTokenType::Eof => write!(f, ""),
-		}
-	}
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-pub struct TokenFromStringError<'a> {
-	source: &'a str,
-}
-impl<'a> Display for TokenFromStringError<'a> {
-	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-		write!(f, "Failed to parse into token; value {}", self.source)
-	}
-}
-impl<'a> Error for TokenFromStringError<'a> {}
-
-impl<'a> TryFrom<&'a str> for ScriptTokenType<'a> {
-	type Error = TokenFromStringError<'a>;
-
-	fn try_from(value: &'a str) -> Result<Self, Self::Error> {
-		match value {
-			"(" => Ok(ScriptTokenType::LeftParen),
-			")" => Ok(ScriptTokenType::RightParen),
-			"{" => Ok(ScriptTokenType::LeftBrace),
-			"}" => Ok(ScriptTokenType::RightBrace),
-			"," => Ok(ScriptTokenType::Comma),
-			"." => Ok(ScriptTokenType::Dot),
-			"-" => Ok(ScriptTokenType::Minus),
-			"+" => Ok(ScriptTokenType::Plus),
-			";" => Ok(ScriptTokenType::Semicolon),
-			"/" => Ok(ScriptTokenType::Slash),
-			"*" => Ok(ScriptTokenType::Asterisk),
-			"!" => Ok(ScriptTokenType::Bang),
-			"!=" => Ok(ScriptTokenType::BangEqual),
-			"=" => Ok(ScriptTokenType::Equal),
-			"==" => Ok(ScriptTokenType::EqualEqual),
-			">" => Ok(ScriptTokenType::Greater),
-			">=" => Ok(ScriptTokenType::GreaterEqual),
-			"<" => Ok(ScriptTokenType::Less),
-			"<=" => Ok(ScriptTokenType::LessEqual),
-			"||" => Ok(ScriptTokenType::DoublePipe),
-			"&&" => Ok(ScriptTokenType::DoubleAmpersand),
-			"%" => Ok(ScriptTokenType::Modulo),
-			"^" => Ok(ScriptTokenType::Caret),
-			"struct" => Ok(ScriptTokenType::Class),
-			"else" => Ok(ScriptTokenType::Else),
-			"fn" => Ok(ScriptTokenType::Function),
-			"for" => Ok(ScriptTokenType::For),
-			"if" => Ok(ScriptTokenType::If),
-			"null" => Ok(ScriptTokenType::Null),
-			"print" => Ok(ScriptTokenType::Print),
-			"return" => Ok(ScriptTokenType::Return),
-			"super" => Ok(ScriptTokenType::Super),
-			"this" => Ok(ScriptTokenType::This),
-			"let" => Ok(ScriptTokenType::Let),
-			"while" => Ok(ScriptTokenType::While),
-			"export" => Ok(ScriptTokenType::Export),
-			"import" => Ok(ScriptTokenType::Import),
-			"as" => Ok(ScriptTokenType::Alias),
-			"from" => Ok(ScriptTokenType::From),
-			_ => Err(TokenFromStringError { source: value }),
-		}
-	}
-}
-
-#[derive(Clone)]
-pub struct ScriptToken<'a> {
-	pub position: Span<'a>,
-	pub token_type: ScriptTokenType<'a>,
-}
-
-impl<'a> Display for ScriptToken<'a> {
-	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-		write!(f, "{}", self.token_type)
-	}
-}
-
-impl<'a> Debug for ScriptToken<'a> {
-	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-		write!(
-			f,
-			"[{}:{}] {:?}",
-			self.position.location_line(),
-			self.position.get_column(),
-			self.token_type
-		)
-	}
-}
-
-#[cfg(test)]
-mod token_tests {
-	use crate::parser::ScriptTokenType;
-
-	#[test]
-	fn match_type_from_string() {
-		assert_eq!(
-			ScriptTokenType::try_from("("),
-			Ok(ScriptTokenType::LeftParen)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from(")"),
-			Ok(ScriptTokenType::RightParen)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from("{"),
-			Ok(ScriptTokenType::LeftBrace)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from("}"),
-			Ok(ScriptTokenType::RightBrace)
-		);
-		assert_eq!(ScriptTokenType::try_from(","), Ok(ScriptTokenType::Comma));
-		assert_eq!(ScriptTokenType::try_from("."), Ok(ScriptTokenType::Dot));
-		assert_eq!(ScriptTokenType::try_from("-"), Ok(ScriptTokenType::Minus));
-		assert_eq!(ScriptTokenType::try_from("+"), Ok(ScriptTokenType::Plus));
-		assert_eq!(
-			ScriptTokenType::try_from(";"),
-			Ok(ScriptTokenType::Semicolon)
-		);
-		assert_eq!(ScriptTokenType::try_from("/"), Ok(ScriptTokenType::Slash));
-		assert_eq!(
-			ScriptTokenType::try_from("*"),
-			Ok(ScriptTokenType::Asterisk)
-		);
-		assert_eq!(ScriptTokenType::try_from("!"), Ok(ScriptTokenType::Bang));
-		assert_eq!(
-			ScriptTokenType::try_from("!="),
-			Ok(ScriptTokenType::BangEqual)
-		);
-		assert_eq!(ScriptTokenType::try_from("="), Ok(ScriptTokenType::Equal));
-		assert_eq!(
-			ScriptTokenType::try_from("=="),
-			Ok(ScriptTokenType::EqualEqual)
-		);
-		assert_eq!(ScriptTokenType::try_from(">"), Ok(ScriptTokenType::Greater));
-		assert_eq!(
-			ScriptTokenType::try_from(">="),
-			Ok(ScriptTokenType::GreaterEqual)
-		);
-		assert_eq!(ScriptTokenType::try_from("<"), Ok(ScriptTokenType::Less));
-		assert_eq!(
-			ScriptTokenType::try_from("<="),
-			Ok(ScriptTokenType::LessEqual)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from("||"),
-			Ok(ScriptTokenType::DoublePipe)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from("&&"),
-			Ok(ScriptTokenType::DoubleAmpersand)
-		);
-		assert_eq!(ScriptTokenType::try_from("%"), Ok(ScriptTokenType::Modulo));
-		assert_eq!(ScriptTokenType::try_from("^"), Ok(ScriptTokenType::Caret));
-		assert_eq!(
-			ScriptTokenType::try_from("struct"),
-			Ok(ScriptTokenType::Class)
-		);
-		assert_eq!(ScriptTokenType::try_from("else"), Ok(ScriptTokenType::Else));
-		assert_eq!(
-			ScriptTokenType::try_from("fn"),
-			Ok(ScriptTokenType::Function)
-		);
-		assert_eq!(ScriptTokenType::try_from("for"), Ok(ScriptTokenType::For));
-		assert_eq!(ScriptTokenType::try_from("if"), Ok(ScriptTokenType::If));
-		assert_eq!(ScriptTokenType::try_from("null"), Ok(ScriptTokenType::Null));
-		assert_eq!(
-			ScriptTokenType::try_from("print"),
-			Ok(ScriptTokenType::Print)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from("return"),
-			Ok(ScriptTokenType::Return)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from("super"),
-			Ok(ScriptTokenType::Super)
-		);
-		assert_eq!(ScriptTokenType::try_from("this"), Ok(ScriptTokenType::This));
-		assert_eq!(ScriptTokenType::try_from("let"), Ok(ScriptTokenType::Let));
-		assert_eq!(
-			ScriptTokenType::try_from("while"),
-			Ok(ScriptTokenType::While)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from("export"),
-			Ok(ScriptTokenType::Export)
-		);
-		assert_eq!(
-			ScriptTokenType::try_from("import"),
-			Ok(ScriptTokenType::Import)
-		);
-		assert_eq!(ScriptTokenType::try_from("as"), Ok(ScriptTokenType::Alias));
-		assert_eq!(ScriptTokenType::try_from("from"), Ok(ScriptTokenType::From));
-	}
-}
diff --git a/src/runtime/maths.rs b/src/runtime/maths.rs
deleted file mode 100644
index 2088f72d5f16875caf235487fd55a68973919ce8..0000000000000000000000000000000000000000
--- a/src/runtime/maths.rs
+++ /dev/null
@@ -1,212 +0,0 @@
-use std::cmp::Ordering;
-use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
-
-/// Represents a numerical value in a script
-#[derive(Copy, Clone, Debug)]
-pub enum Number {
-	Integer(i64),
-	Float(f64),
-}
-
-impl Number {
-	/// Create a new Number representing the provided integer
-	#[inline]
-	pub const fn integer(value: i64) -> Self {
-		Self::Integer(value)
-	}
-	/// Create a new Number representing the provided float
-	#[inline]
-	pub const fn float(value: f64) -> Self {
-		Self::Float(value)
-	}
-	pub const fn is_float(&self) -> bool {
-		matches!(self, Number::Float(..))
-	}
-	pub const fn is_integer(&self) -> bool {
-		matches!(self, Number::Integer(..))
-	}
-	/// Create a copy of the value represented as an Integer internally.
-	/// Will lose information if the value is a float and has a non-zero
-	/// mantissa
-	pub fn as_integer(&self) -> Self {
-		match self {
-			&Self::Float(value) => Self::Integer(value as i64),
-			&Self::Integer(value) => Self::Integer(value),
-		}
-	}
-	/// Create a copy of the value represented as a Float internally.
-	/// Will not lose information in the conversion
-	pub fn as_float(&self) -> Self {
-		match self {
-			&Self::Float(value) => Self::Float(value),
-			&Self::Integer(value) => Self::Float(value as f64),
-		}
-	}
-
-	/// Unwrap this number into a native rust value, represented as
-	/// an integer
-	/// Will lose information if the value is a float and has a non-zero
-	/// mantissa
-	pub fn as_i64(&self) -> i64 {
-		match self {
-			Self::Integer(val) => *val,
-			Self::Float(val) => (*val) as i64,
-		}
-	}
-	/// Unwrap this number into a native rust value, represented as
-	/// a float
-	/// Will not lose information in the conversion
-	pub fn as_f64(&self) -> f64 {
-		match self {
-			Self::Integer(val) => (*val) as f64,
-			Self::Float(val) => *val,
-		}
-	}
-
-	/// Check to see if both value _and_ type matches between this and another
-	/// Number.
-	/// An escape hatch for situations where it is critical that values are (or
-	/// aren't) the same internal type.
-	pub fn matches(&self, other: Number) -> bool {
-		use Number::*;
-		match (*self, other) {
-			(Integer(first), Integer(second)) => first == second,
-			(Float(first), Float(second)) => first == second,
-			_ => false,
-		}
-	}
-}
-
-impl PartialEq for Number {
-	fn eq(&self, other: &Self) -> bool {
-		use Number::*;
-		match (self, other) {
-			(Integer(first), Integer(second)) => first == second,
-			(Float(first), Float(second)) => first == second,
-			(Float(fl), Integer(int)) | (Integer(int), Float(fl)) => (*int as f64) == *fl,
-		}
-	}
-}
-
-impl PartialOrd for Number {
-	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-		use Number::*;
-		match (self, other) {
-			(Integer(first), Integer(second)) => first.partial_cmp(second),
-			(Float(first), Float(second)) => first.partial_cmp(second),
-			(Float(first), Integer(second)) => first.partial_cmp(&(*second as f64)),
-			(Integer(first), Float(second)) => (*first as f64).partial_cmp(second),
-		}
-	}
-}
-
-impl Add for Number {
-	type Output = Number;
-	fn add(self, rhs: Self) -> Self::Output {
-		use Number::*;
-		match (self, rhs) {
-			(Integer(first), Integer(second)) => Integer(first.saturating_add(second)),
-			(Float(first), Float(second)) => Float(first + second),
-			(Float(fl), Integer(int)) | (Integer(int), Float(fl)) => Float(fl + int as f64),
-		}
-	}
-}
-impl AddAssign for Number {
-	#[inline]
-	fn add_assign(&mut self, rhs: Self) {
-		*self = *self + rhs;
-	}
-}
-impl Sub for Number {
-	type Output = Number;
-	fn sub(self, rhs: Self) -> Self::Output {
-		use Number::*;
-		match (self, rhs) {
-			(Integer(first), Integer(second)) => Integer(first.saturating_sub(second)),
-			(Float(first), Float(second)) => Float(first - second),
-			(Float(first), Integer(second)) => Float(first - second as f64),
-			(Integer(first), Float(second)) => Float(first as f64 - second),
-		}
-	}
-}
-impl SubAssign for Number {
-	#[inline]
-	fn sub_assign(&mut self, rhs: Self) {
-		*self = *self - rhs;
-	}
-}
-impl Mul for Number {
-	type Output = Number;
-
-	fn mul(self, rhs: Self) -> Self::Output {
-		use Number::*;
-		match (self, rhs) {
-			(Integer(first), Integer(second)) => Integer(first * second),
-			(Float(first), Float(second)) => Float(first * second),
-			(Float(fl), Integer(int)) | (Integer(int), Float(fl)) => Float(fl * int as f64),
-		}
-	}
-}
-impl MulAssign for Number {
-	#[inline]
-	fn mul_assign(&mut self, rhs: Self) {
-		*self = *self * rhs
-	}
-}
-impl Div for Number {
-	type Output = Number;
-	fn div(self, rhs: Self) -> Self::Output {
-		Number::float(self.as_f64() / rhs.as_f64())
-	}
-}
-impl DivAssign for Number {
-	#[inline]
-	fn div_assign(&mut self, rhs: Self) {
-		*self = *self / rhs;
-	}
-}
-
-#[cfg(test)]
-mod gcse_maths {
-	use crate::runtime::maths::Number;
-
-	#[test]
-	fn eq_ignores_internal() {
-		assert_eq!(Number::integer(123), Number::float(123.0));
-		assert_eq!(Number::integer(123), Number::integer(123));
-		assert_eq!(Number::float(123.0), Number::float(123.0));
-	}
-
-	#[test]
-	fn addition() {
-		let first = Number::integer(123);
-		let second = Number::integer(456);
-		let third = Number::float(789.0);
-		let fourth = Number::float(123.4);
-
-		assert_eq!(first + second, Number::integer(579));
-		assert_eq!(third + fourth, Number::float(912.4));
-	}
-
-	#[test]
-	fn type_coercion() {
-		let first = Number::integer(150);
-		let second = Number::float(5.0);
-
-		assert!(first.is_integer());
-		assert!(second.is_float());
-
-		assert!((first + second).is_float(), "Addition did not create float");
-		assert!(
-			(first - second).is_float(),
-			"Subtraction did not create float"
-		);
-		assert!((first * second).is_float(), "Multiply did not create float");
-		assert!((first / second).is_float(), "Divide did not create float");
-
-		assert!(
-			(first / first).is_float(),
-			"Divide should always create float"
-		);
-	}
-}
diff --git a/src/runtime/mod.rs b/src/runtime/mod.rs
deleted file mode 100644
index ffb2b0426614bcf69cd51c0d0c25909fbb25230b..0000000000000000000000000000000000000000
--- a/src/runtime/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-mod maths;
-
-pub use maths::Number;