diff --git a/forge-script-lang/src/parser/ast.rs b/forge-script-lang/src/parser/ast.rs
index 24690c24670dfede9be8289f83412cf38dcc74f0..5913f3fec256e3f02f457af845154afff7b32333 100644
--- a/forge-script-lang/src/parser/ast.rs
+++ b/forge-script-lang/src/parser/ast.rs
@@ -193,6 +193,107 @@ pub enum ValueExpression {
 	Typeof(TypeofValue),
 }
 
+impl ValueExpression {
+	pub fn add(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::Add,
+		}
+	}
+	pub fn sub(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::Subtract,
+		}
+	}
+	pub fn mul(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::Multiply,
+		}
+	}
+	pub fn div(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::Divide,
+		}
+	}
+	pub fn modulo(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::Modulo,
+		}
+	}
+	pub fn equals(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::Equals,
+		}
+	}
+
+	pub fn bool_and(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::BoolAnd,
+		}
+	}
+
+	pub fn bool_or(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::BoolOr,
+		}
+	}
+
+	pub fn not_equals(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::NotEquals,
+		}
+	}
+
+	pub fn less_than(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::LessThan,
+		}
+	}
+
+	pub fn greater_than(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::GreaterThan,
+		}
+	}
+
+	pub fn less_than_equal(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::LessThanEqual,
+		}
+	}
+
+	pub fn greater_than_equal(lhs: ValueExpression, rhs: ValueExpression) -> Self {
+		ValueExpression::Binary {
+			lhs: Box::new(lhs),
+			rhs: Box::new(rhs),
+			operator: BinaryOp::GreaterThanEqual,
+		}
+	}
+}
+
 #[derive(Clone)]
 #[cfg_attr(any(feature = "debug-ast", test), derive(Debug))]
 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
diff --git a/forge-script-lang/src/parser/forge_grammar.lalrpop b/forge-script-lang/src/parser/forge_grammar.lalrpop
index 68a5d3d813cc29cda32d20015361276866abe19e..82e6ff301cd07a22bd8c83d0497ab8a22635ea53 100644
--- a/forge-script-lang/src/parser/forge_grammar.lalrpop
+++ b/forge-script-lang/src/parser/forge_grammar.lalrpop
@@ -5,158 +5,74 @@ use crate::runtime::numbers::Number;
 grammar<'a>;
 
 pub Program: Program = {
-    ExpressionList => Program(<>)
-};
-
-Block: Option<ExpressionList> = {
-    "{" <ExpressionList?> "}" => <>,
-};
-
-ExpressionList: ExpressionList = {
-    <e:Expression> <b:";"?> => {
-        ExpressionList {
-            expressions: vec![e],
-            is_void: b.is_some(),
-        }
-    },
-    <e:Expression> ";" <mut ls:ExpressionList> => {
-        let mut new = vec![e];
-        new.append(&mut ls.expressions);
-
-        ExpressionList {
-            expressions: new,
-            is_void: ls.is_void,
-        }
-    }
-};
+    <Expression> => Program(ExpressionList { expressions: vec![<>], is_void: false })
+}
 
 pub Expression: Expression = {
-    ValueExpression => Expression::Value(<>),
-    VoidExpression => Expression::Void(<>),
-};
-
-VoidExpression: VoidExpression = {
-    AsVoid<PrintStmt> => <>,
-    AsVoid<ImportStmt> => <>,
-    AsVoid<ExportStmt> => <>,
-};
-
-ValueExpression: ValueExpression = {
-    AsValue<Literal> => <>,
-    AsValue<Identifier> => <>,
-    AsValue<IfStatement> => <>,
-    "(" <lhs:ValueExpression> "+" <rhs:ValueExpression> ")" => ValueExpression::Binary { lhs: Box::new(lhs), rhs: Box::new(rhs), operator: BinaryOp::Add },
-    "typeof" <expr:ValueExpression> => TypeofValue(Box::new(expr)).into(),
-    "-" <expr:ValueExpression> => ValueExpression::Unary { operand: Box::new(expr), operator: UnaryOp::Negate },
-    "!" <expr:ValueExpression> => ValueExpression::Unary { operand: Box::new(expr), operator: UnaryOp::Not },
-    "(" <expr:ValueExpression> ")" => GroupedExpression { inner: Box::new(expr) }.into(),
+    <TopExpression> => Expression::Value(<>),
 }
 
-//ValueExpression: ValueExpression = {
-//    #[precedence(level="100")]
-//    "(" <expr:ValueExpression> ")" => GroupedExpression { inner: Box::new(expr) }.into(),
-//    #[precedence(level="0")]
-//    Literal => ValueExpression::Literal(<>),
-//    #[precedence(level="0")]
-//    Identifier => <>.into(),
-//
-//    #[precedence(level="2")]
-//    "typeof" <expr:ValueExpression> => TypeofValue(Box::new(expr)).into(),
-//    #[precedence(level="2")]
-//    "-" <expr:ValueExpression> => ValueExpression::Unary { operand: Box::new(expr), operator: UnaryOp::Negate },
-//    #[precedence(level="2")]
-//    "!" <expr:ValueExpression> => ValueExpression::Unary { operand: Box::new(expr), operator: UnaryOp::Not },
-//
-//    #[precedence(level = "3")]
-//    IfStatement => <>.into(),
-//
-//    #[precedence(level="4")] #[assoc(side="left")]
-//    <lhs:ValueExpression> "*" <rhs:ValueExpression> => {
-//        ValueExpression::Binary {
-//            lhs: Box::new(lhs),
-//            rhs: Box::new(rhs),
-//            operator: BinaryOp::Multiply,
-//        }
-//    },
-//    #[precedence(level="4")] #[assoc(side="left")]
-//    <lhs:ValueExpression> "/" <rhs:ValueExpression> => {
-//        ValueExpression::Binary {
-//            lhs: Box::new(lhs),
-//            rhs: Box::new(rhs),
-//            operator: BinaryOp::Divide,
-//        }
-//    },
-//    #[precedence(level="6")] #[assoc(side="left")]
-//    <lhs:ValueExpression> "+" <rhs:ValueExpression> => {
-//        ValueExpression::Binary {
-//            lhs: Box::new(lhs),
-//            rhs: Box::new(rhs),
-//            operator: BinaryOp::Add,
-//        }
-//    },
-//    #[precedence(level="6")] #[assoc(side="left")]
-//    <lhs:ValueExpression> "-" <rhs:ValueExpression> => {
-//        ValueExpression::Binary {
-//            lhs: Box::new(lhs),
-//            rhs: Box::new(rhs),
-//            operator: BinaryOp::Subtract,
-//        }
-//    },
-//};
-
-AsVoid<R>: VoidExpression = {
-    R => <>.into()
+TopExpression: ValueExpression = {
+    <BoolOrExpression> => <>,
 }
-AsValue<R>: ValueExpression = {
-    R => <>.into()
+
+BoolOrExpression: ValueExpression = {
+    <BoolAndExpression> => <>,
+    <lhs:BoolOrExpression> "||" <rhs:BoolAndExpression> => ValueExpression::bool_or(lhs, rhs),
 }
 
-TypeofStmt: TypeofValue = {
-    "typeof" <ValueExpression> => TypeofValue(Box::new(<>))
+BoolAndExpression: ValueExpression = {
+    <EqualityExpression> => <>,
+    <lhs:BoolAndExpression> "&&" <rhs:EqualityExpression> => ValueExpression::bool_and(lhs, rhs),
 }
 
-PrintStmt: Print = {
-    "print" <expr:ValueExpression> => Print { expr: Box::new(expr) },
+EqualityExpression: ValueExpression = {
+    <ComparisonExpression> => <>,
+    <lhs:EqualityExpression> "==" <rhs:ComparisonExpression> => ValueExpression::equals(lhs, rhs),
+    <lhs:EqualityExpression> "!=" <rhs:ComparisonExpression> => ValueExpression::not_equals(lhs, rhs),
 }
-ImportStmt: Import = {
-    "import" "{" <items:IdentifierList> "}" "from" <source:StringValue> => Import { source, items },
+
+ComparisonExpression: ValueExpression = {
+    <AdditiveExpression> => <>,
+    <lhs:ComparisonExpression> "<" <rhs:AdditiveExpression> => ValueExpression::less_than(lhs, rhs),
+    <lhs:ComparisonExpression> ">" <rhs:AdditiveExpression> => ValueExpression::greater_than(lhs, rhs),
+    <lhs:ComparisonExpression> "<=" <rhs:AdditiveExpression> => ValueExpression::greater_than_equal(lhs, rhs),
+    <lhs:ComparisonExpression> ">=" <rhs:AdditiveExpression> => ValueExpression::greater_than_equal(lhs, rhs),
 }
-ExportStmt: Export = {
-    "export" "{" <items:IdentifierList> "}" => Export { items },
+
+AdditiveExpression: ValueExpression = {
+    <MultiplicativeExpression> => <>,
+    <lhs:AdditiveExpression> "+" <rhs:MultiplicativeExpression> => ValueExpression::add(lhs, rhs),
+    <lhs:AdditiveExpression> "-" <rhs:MultiplicativeExpression> => ValueExpression::sub(lhs, rhs),
 }
 
-IfStatement: Conditional = {
-    BareIfStatement => Conditional { blocks: vec![<>], fallback: None },
-    <fi:BareIfStatement> "else" <bl:Block> => Conditional { blocks: vec![fi], fallback: bl },
-    <fi:BareIfStatement> "else" <ls:IfStatement> => {
-        let mut ls = ls;
-        let mut new = vec![fi];
-        new.append(&mut ls.blocks);
-        Conditional {
-            blocks: new,
-            fallback: ls.fallback,
-        }
-    }
-};
+MultiplicativeExpression: ValueExpression = {
+    <UnaryExpression> => <>,
+    <lhs:MultiplicativeExpression> "*" <rhs:UnaryExpression> => ValueExpression::mul(lhs, rhs),
+    <lhs:MultiplicativeExpression> "/" <rhs:UnaryExpression> => ValueExpression::div(lhs, rhs),
+    <lhs:MultiplicativeExpression> "%" <rhs:UnaryExpression> => ValueExpression::modulo(lhs, rhs),
+}
 
-BareIfStatement: GuardedBlock = {
-    "if" <guard:ValueExpression> <bl:Block> => {
-        GuardedBlock {
-            block: bl.unwrap_or_default(),
-            guard: Box::new(guard),
-        }
-    }
-};
+UnaryExpression: ValueExpression = {
+    <IndexedExpression> => <>,
+    "typeof" <UnaryExpression> => TypeofValue(Box::new(<>)).into(),
+    "!" <UnaryExpression> => ValueExpression::Unary { operand: Box::new(<>), operator: UnaryOp::Not },
+    "-" <UnaryExpression> => ValueExpression::Unary { operand: Box::new(<>), operator: UnaryOp::Negate },
+}
 
-ParameterList = ListOf<ValueExpression>;
-IdentifierList = ListOf<IdentifierNode>;
+IndexedExpression: ValueExpression = {
+    // Include indexing expression here
+    // <idx:IndexedExpression> "." <id:Identifier> => Indexed access
+    <BaseExpression> => <>,
+}
 
-IdentifierNode: IdentifierNode = {
-    IdentifierAlias => IdentifierNode::Alias(<>),
-    Identifier => IdentifierNode::Direct(<>),
-};
+BaseExpression: ValueExpression = {
+    <Literal> => <>.into(),
+    <Identifier> => <>.into(),
+    "(" <TopExpression> ")" => GroupedExpression { inner: Box::new(<>) }.into(),
+}
 
-IdentifierAlias: IdentifierAlias = {
+IdentifierAsAlias: IdentifierAlias = {
     <base:Identifier> "as" <alias:Identifier> => IdentifierAlias(base.0, alias.0),
 };
 
@@ -178,16 +94,6 @@ StringValue: String = {
     "owned_string" => <>,
 };
 
-ListOf<T>: Vec<T> = {
-    <mut v:(<T> ",")+> <e:T?> => match e {
-        None => v,
-        Some(e) => {
-            v.push(e);
-            v
-        }
-    }
-};
-
 extern {
     type Location = usize;
     type Error = String;
diff --git a/forge-script-lang/src/parser/forge_script.rs b/forge-script-lang/src/parser/forge_script.rs
index 78b7df73129e786c33449a3b2371fb7f9a95cdb6..a554eb220045e0c5586acd2c1cd535c3224a325a 100644
--- a/forge-script-lang/src/parser/forge_script.rs
+++ b/forge-script-lang/src/parser/forge_script.rs
@@ -48,7 +48,11 @@ mod grammar_test {
 	#[test_case("null" => matches Ok(_) ; "Parse literal null")]
 	#[test_case("if foo {}" => matches Ok(_) ; "Parse conditional")]
 	#[test_case("2 * 4 - 3" => matches Ok(_) ; "Parse arithmetic")]
+	#[test_case("10 - 2 * 4 + 3" => matches Ok(_) ; "Parse arithmetic reverse")]
 	fn expression_parsing(prog: &str) -> Result<Expression, String> {
-		parse_expression(prog)
+		parse_expression(prog).map(|foo| {
+			dbg!(&foo);
+			foo
+		})
 	}
 }
diff --git a/forge-script-lang/src/runtime/vm/compile.rs b/forge-script-lang/src/runtime/vm/compile.rs
index f985cd1e2d6890b6d1f3084d06dcfde3276ae69a..e1fb05078179bafbb5bfe2398d9e9484eaa66706 100644
--- a/forge-script-lang/src/runtime/vm/compile.rs
+++ b/forge-script-lang/src/runtime/vm/compile.rs
@@ -65,15 +65,6 @@ impl<'a> Compiler<'a> {
 		Ok(cmp)
 	}
 
-	pub fn as_parsing_table(&mut self) -> ParsingRules {
-		rule_table!((
-			ParsingRuleType::LeftParen,
-			Some(Box::new(compile_expression)),
-			None,
-			RulePrecedence::None,
-		),)
-	}
-
 	pub fn chunk(&self) -> &Chunk {
 		&self.chunk
 	}