diff --git a/examples/basic_condition.ion b/examples/basic_condition.ion
index 2c0c6c4d2afd12e8e152df8a364a64c6c1e0cdb4..10bd1f4513a40fc56154b03c8a78ee18f2ea8d4a 100644
--- a/examples/basic_condition.ion
+++ b/examples/basic_condition.ion
@@ -1,5 +1,5 @@
-if 3 == 2
-    echo fail
-else
+if test 3 -eq 3
     echo pass
+else
+    echo fail
 end
diff --git a/examples/else_if.ion b/examples/else_if.ion
new file mode 100644
index 0000000000000000000000000000000000000000..4e75c01bfc866769db3872fa0fa4fe62320e4623
--- /dev/null
+++ b/examples/else_if.ion
@@ -0,0 +1,7 @@
+if test 1 -gt 5
+    echo one
+else if test 1 -eq 1
+    echo two
+else
+    echo three
+end
diff --git a/examples/else_if.out b/examples/else_if.out
new file mode 100644
index 0000000000000000000000000000000000000000..f719efd430d52bcfc8566a43b2eb655688d38871
--- /dev/null
+++ b/examples/else_if.out
@@ -0,0 +1 @@
+two
diff --git a/examples/fail.ion b/examples/fail.ion
index 5dd0e614a08152f65ff1984d50805b9f62c29903..aafe277b20adb6ed148c216c829c39197e7d0348 100644
--- a/examples/fail.ion
+++ b/examples/fail.ion
@@ -1,4 +1,4 @@
-if 3 == 2
+if test 3 -eq 2
     echo pass
 else
     echo fail
diff --git a/examples/fn.ion b/examples/fn.ion
index f5097892927d33b0dd4b681e701ccd98aa1ecdb8..faac03ac1c87118598358acf5b4351f23efc65fc 100644
--- a/examples/fn.ion
+++ b/examples/fn.ion
@@ -5,3 +5,11 @@ fn test a b c
 end
 
 test hello world goodbye
+
+fn another_test
+    for i in 1..10
+        echo $i
+    end
+end
+
+another_test
diff --git a/examples/fn.out b/examples/fn.out
index 206b65b89fdf5d702ee8ecf3f4e3c35bc3defd56..c77d34931dc6e380bd98c54271da98081f003be4 100644
--- a/examples/fn.out
+++ b/examples/fn.out
@@ -1,3 +1,12 @@
 hello
 world
 goodbye
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/examples/for.ion b/examples/for.ion
index aedf731b17f4ea1f89a6fa66591922662e5182eb..591235886f5d428692c437456411cd8d9c7783a4 100644
--- a/examples/for.ion
+++ b/examples/for.ion
@@ -1,3 +1,11 @@
+for i in 1..6
+  echo $i
+end
+
+for i in 1...5
+  echo $i
+end
+
 for i in 1 2 3 4 5
   echo $i
 end
diff --git a/examples/for.out b/examples/for.out
index 8a1218a1024a212bb3db30becd860315f9f3ac52..90048fced299df43e1088f8e3093c53583a87a94 100644
--- a/examples/for.out
+++ b/examples/for.out
@@ -3,3 +3,13 @@
 3
 4
 5
+1
+2
+3
+4
+5
+1
+2
+3
+4
+5
diff --git a/examples/advanced_conditions.ion b/examples/nested_conditions.ion
similarity index 76%
rename from examples/advanced_conditions.ion
rename to examples/nested_conditions.ion
index 60230b9882c2e1062b3b2ed86d601c2b495e1dd3..ffcb304ca3e1a898e45f2d32b3136e28a6f9a6a1 100644
--- a/examples/advanced_conditions.ion
+++ b/examples/nested_conditions.ion
@@ -1,10 +1,10 @@
-if a == a
+if test a = a
   echo true a == a
-  if b != b
+  if test b != b
     echo true b != b
   else
     echo false b != b
-    if 3 > 2
+    if test 3 -gt 2
       echo "true 3 > 2"
     else
       echo "false 3 > 2"
diff --git a/examples/advanced_conditions.out b/examples/nested_conditions.out
similarity index 100%
rename from examples/advanced_conditions.out
rename to examples/nested_conditions.out
diff --git a/examples/nested_for.ion b/examples/nested_for.ion
new file mode 100644
index 0000000000000000000000000000000000000000..2b83bd0bf69cc2da86af98629189d813c3992f8c
--- /dev/null
+++ b/examples/nested_for.ion
@@ -0,0 +1,5 @@
+for a in 0..10
+    for b in 1..10
+      echo $a$b
+    end
+end
diff --git a/examples/nested_for.out b/examples/nested_for.out
new file mode 100644
index 0000000000000000000000000000000000000000..12a2653075cb7aa31f53024475b3b059bec5984f
--- /dev/null
+++ b/examples/nested_for.out
@@ -0,0 +1,90 @@
+01
+02
+03
+04
+05
+06
+07
+08
+09
+11
+12
+13
+14
+15
+16
+17
+18
+19
+21
+22
+23
+24
+25
+26
+27
+28
+29
+31
+32
+33
+34
+35
+36
+37
+38
+39
+41
+42
+43
+44
+45
+46
+47
+48
+49
+51
+52
+53
+54
+55
+56
+57
+58
+59
+61
+62
+63
+64
+65
+66
+67
+68
+69
+71
+72
+73
+74
+75
+76
+77
+78
+79
+81
+82
+83
+84
+85
+86
+87
+88
+89
+91
+92
+93
+94
+95
+96
+97
+98
+99
diff --git a/examples/while.ion b/examples/while.ion
new file mode 100644
index 0000000000000000000000000000000000000000..8bd808f312bb11236683ebc98c4104bd285a3145
--- /dev/null
+++ b/examples/while.ion
@@ -0,0 +1,5 @@
+let a = 1
+while test $a -lt 10
+    echo $a
+    let a += 1
+end
diff --git a/examples/while.out b/examples/while.out
new file mode 100644
index 0000000000000000000000000000000000000000..07193989308c972f8a2d0f1b3a15c29ea4ac565b
--- /dev/null
+++ b/examples/while.out
@@ -0,0 +1,9 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/src/flow_control.rs b/src/flow_control.rs
index ad5d2de964f97369924999d019986bca5e0c4e79..929045fcb6b4ec30ecb5cb452820449c883a5d0d 100644
--- a/src/flow_control.rs
+++ b/src/flow_control.rs
@@ -1,21 +1,34 @@
 use parser::peg::Pipeline;
 
+#[derive(Debug, PartialEq, Clone)]
+pub struct ElseIf {
+    pub expression: Pipeline,
+    pub success:    Vec<Statement>
+}
+
 #[derive(Debug, PartialEq, Clone)]
 pub enum Statement {
     If {
-        left: String,
-        comparitor: Comparitor,
-        right: String
+        expression: Pipeline,
+        success: Vec<Statement>,
+        else_if: Vec<ElseIf>,
+        failure: Vec<Statement>
     },
+    ElseIf(ElseIf),
     Function {
         name: String,
-        args: Vec<String>
+        args: Vec<String>,
+        statements: Vec<Statement>
     },
-    For{
+    For {
         variable: String,
         values: String,
+        statements: Vec<Statement>
+    },
+    While {
+        expression: Pipeline,
+        statements: Vec<Statement>
     },
-    While { expression: Pipeline },
     Else,
     End,
     // TODO: Vec is unnecessary here because there will always be one pipeline parsed
@@ -23,55 +36,86 @@ pub enum Statement {
     Default
 }
 
-impl Statement {
-    pub fn is_flow_control(&self) -> bool {
-        match *self {
-            Statement::If{..}  |
-            Statement::Else    |
-            Statement::For{..} |
-            Statement::While{..} |
-            Statement::Function{..} => true,
-
-            Statement::End           |
-            Statement::Pipelines(..) |
-            Statement::Default      => false
+pub struct FlowControl {
+    pub level:             usize,
+    pub current_statement: Statement,
+    pub current_if_mode:      u8 // { 0 = SUCCESS; 1 = FAILURE }
+}
 
+impl Default for FlowControl {
+    fn default() -> FlowControl {
+        FlowControl {
+            level:             0,
+            current_statement: Statement::Default,
+            current_if_mode:   0,
         }
     }
 }
 
-#[derive(Debug, PartialEq, Clone)]
-pub enum Comparitor {
-    Equal,
-    NotEqual,
-    GreaterThan,
-    LessThan,
-    GreaterThanOrEqual,
-    LessThanOrEqual
-}
-
-pub struct CodeBlock {
-    pub pipelines: Vec<Pipeline>,
+#[derive(Clone)]
+pub struct Function {
+    pub name: String,
+    pub args: Vec<String>,
+    pub statements: Vec<Statement>
 }
 
-pub struct Mode {
-    pub value: bool,
+pub fn collect_loops<I>(iterator: &mut I, statements: &mut Vec<Statement>, level: &mut usize)
+    where I: Iterator<Item = Statement>
+{
+    #[allow(while_let_on_iterator)]
+    while let Some(statement) = iterator.next() {
+        match statement {
+            Statement::While{..} | Statement::For{..} | Statement::If{..} |
+                Statement::Function{..} => *level += 1,
+            Statement::End if *level == 1 => { *level = 0; break },
+            Statement::End => *level -= 1,
+            _ => (),
+        }
+        statements.push(statement);
+    }
 }
 
-pub struct FlowControl {
-    pub modes: Vec<Mode>,
-    pub collecting_block: bool,
-    pub current_block: CodeBlock,
-    pub current_statement: Statement, /* pub prompt: &'static str,  // Custom prompt while collecting code block */
-}
+pub fn collect_if<I>(iterator: &mut I, success: &mut Vec<Statement>, else_if: &mut Vec<ElseIf>,
+    failure: &mut Vec<Statement>, level: &mut usize, mut current_block: u8)
+        -> Result<u8, &'static str>
+    where I: Iterator<Item = Statement>
+{
+    #[allow(while_let_on_iterator)]
+    while let Some(statement) = iterator.next() {
+        match statement {
+            Statement::While{..} | Statement::For{..} | Statement::If{..} |
+                Statement::Function{..} => *level += 1,
+            Statement::ElseIf(ref elseif) if *level == 1 => {
+                if current_block == 1 {
+                    return Err("ion: syntax error: else block already given");
+                } else {
+                    current_block = 2;
+                    else_if.push(elseif.clone());
+                    continue
+                }
+            }
+            Statement::Else if *level == 1 => {
+                current_block = 1;
+                continue
+            },
+            Statement::Else if *level == 1 && current_block == 1 => {
+                return Err("ion: syntax error: else block already given");
+            }
+            Statement::End if *level == 1 => { *level = 0; break },
+            Statement::End => *level -= 1,
+            _ => (),
+        }
 
-impl Default for FlowControl {
-    fn default() -> FlowControl {
-        FlowControl {
-            modes: vec![],
-            collecting_block: false,
-            current_block: CodeBlock { pipelines: vec![] },
-            current_statement: Statement::Default,
+        match current_block {
+            0 => success.push(statement),
+            1 => failure.push(statement),
+            2 => {
+                let mut last = else_if.last_mut().unwrap(); // This is a bug if there isn't a value
+                last.success.push(statement);
+            }
+            _ => unreachable!()
         }
     }
+
+    Ok(current_block)
 }
diff --git a/src/function.rs b/src/function.rs
deleted file mode 100644
index d6edd6d45d534db1cfcaa578f596a21c9c3c784e..0000000000000000000000000000000000000000
--- a/src/function.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use parser::peg::Pipeline;
-
-#[derive(Clone)]
-pub struct Function {
-    pub name: String,
-    pub pipelines: Vec<Pipeline>,
-    pub args: Vec<String>
-}
diff --git a/src/main.rs b/src/main.rs
index 409dd4834e205a592fcacc148875bc796241ea1a..7c8df788f13de8bcb750afeff93408549e41e95c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,5 @@
-#![deny(warnings)]
+// #![deny(warnings)]
+#![allow(unknown_lints)]
 #![feature(box_syntax)]
 #![feature(plugin)]
 #![plugin(peg_syntax_ext)]
@@ -21,12 +22,11 @@ use completer::MultiCompleter;
 use directory_stack::DirectoryStack;
 use variables::Variables;
 use status::*;
-use function::Function;
 use pipe::execute_pipeline;
 use parser::shell_expand::ExpandErr;
 use parser::{expand_string, ForExpression, StatementSplitter};
 use parser::peg::{parse, Pipeline};
-use flow_control::{FlowControl, Statement, Comparitor};
+use flow_control::{ElseIf, FlowControl, Function, Statement, collect_loops, collect_if};
 
 pub mod completer;
 pub mod pipe;
@@ -34,7 +34,6 @@ pub mod directory_stack;
 pub mod to_num;
 pub mod variables;
 pub mod status;
-pub mod function;
 pub mod flow_control;
 mod builtins;
 mod parser;
@@ -254,170 +253,326 @@ impl Shell {
     }
 
     pub fn prompt(&self) -> String {
-        let mut prompt = self.flow_control.modes.iter().rev().fold(String::new(), |acc, mode| {
-            acc +
-            if mode.value {
-                "+ "
-            } else {
-                "- "
+        if self.flow_control.level == 0 {
+            let prompt_var = self.variables.get_var_or_empty("PROMPT");
+            match expand_string(&prompt_var, &self.variables, &self.directory_stack) {
+                Ok(expanded_string) => expanded_string,
+                Err(ExpandErr::UnmatchedBraces(position)) => {
+                    let stderr = io::stderr();
+                    let mut stderr = stderr.lock();
+                    let _ = writeln!(stderr, "ion: expand error: unmatched braces\n{}\n{}^",
+                        prompt_var, iter::repeat("-").take(position).collect::<String>());
+                    String::from("ERROR: ")
+                },
+                Err(ExpandErr::InnerBracesNotImplemented) => {
+                    let stderr = io::stderr();
+                    let mut stderr = stderr.lock();
+                    let _ = stderr.write_all(b"ion: expand error: inner braces not yet implemented\n");
+                    String::from("ERROR: ")
+                }
             }
-        }).to_string();
+        } else {
+            "    ".repeat(self.flow_control.level as usize)
+        }
+    }
 
-        match self.flow_control.current_statement {
-            Statement::For { .. } => {
-                prompt.push_str("for> ");
-            },
-            Statement::While { .. } => {
-                prompt.push_str("while> ");
-            },
-            Statement::Function { .. } => {
-                prompt.push_str("fn> ");
-            },
-            _ => {
-                let prompt_var = self.variables.get_var_or_empty("PROMPT");
-                match expand_string(&prompt_var, &self.variables, &self.directory_stack) {
-                    Ok(ref expanded_string) => prompt.push_str(expanded_string),
-                    Err(ExpandErr::UnmatchedBraces(position)) => {
-                        let stderr = io::stderr();
-                        let mut stderr = stderr.lock();
-                        let _ = writeln!(stderr, "ion: expand error: unmatched braces\n{}\n{}^",
-                            prompt_var, iter::repeat("-").take(position).collect::<String>());
-                        prompt.push_str("ERROR: ");
-                    },
-                    Err(ExpandErr::InnerBracesNotImplemented) => {
-                        let stderr = io::stderr();
-                        let mut stderr = stderr.lock();
-                        let _ = stderr.write_all(b"ion: expand error: inner braces not yet implemented\n");
-                        prompt.push_str("ERROR: ");
+    fn execute_statements(&mut self, mut statements: Vec<Statement>) {
+        let mut iterator = statements.drain(..);
+        while let Some(statement) = iterator.next() {
+            match statement {
+                Statement::While { expression, mut statements } => {
+                    self.flow_control.level += 1;
+                    collect_loops(&mut iterator, &mut statements, &mut self.flow_control.level);
+                    self.execute_while(expression, statements);
+                },
+                Statement::For { variable, values, mut statements } => {
+                    self.flow_control.level += 1;
+                    collect_loops(&mut iterator, &mut statements, &mut self.flow_control.level);
+                    self.execute_for(&variable, &values, statements);
+                },
+                Statement::If { expression, mut success, mut else_if, mut failure } => {
+                    self.flow_control.level += 1;
+                    if let Err(why) = collect_if(&mut iterator, &mut success, &mut else_if,
+                        &mut failure, &mut self.flow_control.level, 0) {
+                            let stderr = io::stderr();
+                            let mut stderr = stderr.lock();
+                            let _ = writeln!(stderr, "{}", why);
+                            self.flow_control.level = 0;
+                            self.flow_control.current_if_mode = 0;
+                            println!("ABC");
+                            return
+                        }
+                    self.execute_if(expression, success, else_if, failure);
+                },
+                Statement::Function { name, args, mut statements } => {
+                    self.flow_control.level += 1;
+                    collect_loops(&mut iterator, &mut statements, &mut self.flow_control.level);
+                    self.functions.insert(name.clone(), Function {
+                        name:       name,
+                        args:       args,
+                        statements: statements
+                    });
+                }
+                Statement::Pipelines(mut pipelines) => {
+                    for pipeline in pipelines.drain(..) {
+                        self.run_pipeline(&pipeline, false);
                     }
                 }
+                _ => {}
             }
         }
-
-        prompt
     }
 
-    fn on_command(&mut self, command_string: &str) {
-        for statement in StatementSplitter::new(command_string).map(parse) {
-            if statement.is_flow_control() {
-                self.flow_control.current_statement = statement.clone();
-                self.flow_control.collecting_block = true;
-            }
+    fn execute_while(&mut self, expression: Pipeline, statements: Vec<Statement>) {
+        while self.run_pipeline(&expression, false) == Some(SUCCESS) {
+            // Cloning is needed so the statement can be re-iterated again if needed.
+            self.execute_statements(statements.clone())
+        }
+    }
 
-            match statement {
-                Statement::End                         => self.handle_end(),
-                Statement::If{left, right, comparitor} => self.handle_if(left, comparitor, right),
-                Statement::Pipelines(pipelines)        => { let _ = self.handle_pipelines(pipelines, false); },
-                _                                      => {}
+    fn execute_for(&mut self, variable: &str, values: &str, statements: Vec<Statement>) {
+        match ForExpression::new(values, &self.directory_stack, &self.variables) {
+            ForExpression::Normal(expression) => {
+                for value in expression.split_whitespace() {
+                    self.variables.set_var(variable, value);
+                    self.execute_statements(statements.clone())
+                }
+            },
+            ForExpression::Range(start, end) => {
+                for value in (start..end).map(|x| x.to_string()) {
+                    self.variables.set_var(variable, &value);
+                    self.execute_statements(statements.clone())
+                }
             }
         }
     }
 
-    fn handle_if(&mut self, left: String, comparitor: Comparitor, right: String) {
-        let left  = expand_string(&left, &self.variables, &self.directory_stack).unwrap_or_else(|_| "".to_string());
-        let right = expand_string(&right, &self.variables, &self.directory_stack).unwrap_or_else(|_| "".to_string());
-
-        let value = match comparitor {
-            Comparitor::GreaterThan        => { left >  right },
-            Comparitor::GreaterThanOrEqual => { left >= right },
-            Comparitor::LessThan           => { left <  right },
-            Comparitor::LessThanOrEqual    => { left <= right },
-            Comparitor::Equal              => { left == right },
-            Comparitor::NotEqual           => { left != right },
-        };
-
-        self.flow_control.modes.push(flow_control::Mode{value: value})
+    fn execute_if(&mut self, expression: Pipeline, success: Vec<Statement>,
+        mut else_if: Vec<ElseIf>, failure: Vec<Statement>)
+    {
+        match self.run_pipeline(&expression, false) {
+            Some(SUCCESS) => self.execute_statements(success),
+            _             => {
+                for elseif in else_if.drain(..) {
+                    if self.run_pipeline(&elseif.expression, false) == Some(SUCCESS) {
+                        self.execute_statements(elseif.success);
+                        return
+                    }
+                }
+                self.execute_statements(failure);
+            }
+        }
     }
 
-    fn handle_end(&mut self){
-        self.flow_control.collecting_block = false;
-        match self.flow_control.current_statement.clone() {
-            Statement::While{ref expression} => {
-                let block_jobs: Vec<Pipeline> = self.flow_control.current_block
-                    .pipelines.drain(..).collect();
-                while self.run_pipeline(expression, false) == Some(SUCCESS) {
-                    for pipeline in &block_jobs {
-                        self.run_pipeline(pipeline, false);
+    fn execute_toplevel<I>(&mut self, iterator: &mut I, statement: Statement) -> Result<(), &'static str>
+        where I: Iterator<Item = Statement>
+    {
+        match statement {
+            // Collect the statements for the while loop, and if the loop is complete,
+            // execute the while loop with the provided expression.
+            Statement::While { expression, mut statements } => {
+                self.flow_control.level += 1;
+
+                // Collect all of the statements contained within the while block.
+                collect_loops(iterator, &mut statements, &mut self.flow_control.level);
+
+                if self.flow_control.level == 0 {
+                    // All blocks were read, thus we can immediately execute now
+                    self.execute_while(expression, statements);
+                } else {
+                    // Store the partial `Statement::While` to memory
+                    self.flow_control.current_statement = Statement::While {
+                        expression: expression,
+                        statements: statements,
                     }
                 }
             },
-            Statement::For{variable: ref var, values: ref vals} => {
-                let block_jobs: Vec<Pipeline> = self.flow_control
-                    .current_block
-                    .pipelines
-                    .drain(..)
-                    .collect();
-
-                match ForExpression::new(vals.as_str(), &self.directory_stack, &self.variables) {
-                    ForExpression::Normal(expression) => {
-                        for value in expression.split_whitespace() {
-                            self.variables.set_var(var, value);
-                            for pipeline in &block_jobs {
-                                self.run_pipeline(pipeline, false);
-                            }
-                        }
-                    },
-                    ForExpression::Range(start, end) => {
-                        for value in (start..end).map(|x| x.to_string()) {
-                            self.variables.set_var(var, &value);
-                            for pipeline in &block_jobs {
-                                self.run_pipeline(pipeline, false);
-                            }
-                        }
+            // Collect the statements for the for loop, and if the loop is complete,
+            // execute the for loop with the provided expression.
+            Statement::For { variable, values, mut statements } => {
+                self.flow_control.level += 1;
+
+                // Collect all of the statements contained within the while block.
+                collect_loops(iterator, &mut statements, &mut self.flow_control.level);
+
+                if self.flow_control.level == 0 {
+                    // All blocks were read, thus we can immediately execute now
+                    self.execute_for(&variable, &values, statements);
+                } else {
+                    // Store the partial `Statement::For` to memory
+                    self.flow_control.current_statement = Statement::For {
+                        variable:   variable,
+                        values:     values,
+                        statements: statements,
                     }
                 }
             },
-            Statement::Function{ref name, ref args} => {
-                    let block_jobs: Vec<Pipeline> = self.flow_control
-                        .current_block
-                        .pipelines
-                        .drain(..)
-                        .collect();
-                self.functions.insert(name.clone(), Function { name: name.clone(), pipelines: block_jobs.clone(), args: args.clone() });
+            // Collect the statements needed for the `success`, `else_if`, and `failure`
+            // conditions; then execute the if statement if it is complete.
+            Statement::If { expression, mut success, mut else_if, mut failure } => {
+                self.flow_control.level += 1;
+
+                // Collect all of the success and failure statements within the if condition.
+                // The `mode` value will let us know whether the collector ended while
+                // collecting the success block or the failure block.
+                let mode = collect_if(iterator, &mut success, &mut else_if,
+                    &mut failure, &mut self.flow_control.level, 0)?;
+
+                if self.flow_control.level == 0 {
+                    // All blocks were read, thus we can immediately execute now
+                    self.execute_if(expression, success, else_if, failure);
+                } else {
+                    // Set the mode and partial if statement in memory.
+                    self.flow_control.current_if_mode = mode;
+                    self.flow_control.current_statement = Statement::If {
+                        expression: expression,
+                        success:    success,
+                        else_if:    else_if,
+                        failure:    failure
+                    };
+                }
             },
-            Statement::If{..} | Statement::Else => {
-                self.flow_control.modes.pop();
-                if self.flow_control.modes.is_empty() {
-                    let block_jobs: Vec<Pipeline> = self.flow_control
-                        .current_block
-                        .pipelines
-                        .drain(..)
-                        .collect();
-                    for pipeline in &block_jobs {
-                        self.run_pipeline(pipeline, false);
+            // Collect the statements needed by the function and add the function to the
+            // list of functions if it is complete.
+            Statement::Function { name, args, mut statements } => {
+                self.flow_control.level += 1;
+
+                // The same logic that applies to loops, also applies here.
+                collect_loops(iterator, &mut statements, &mut self.flow_control.level);
+
+                if self.flow_control.level == 0 {
+                    // All blocks were read, thus we can add it to the list
+                    self.functions.insert(name.clone(), Function {
+                        name:       name,
+                        args:       args,
+                        statements: statements
+                    });
+                } else {
+                    // Store the partial function declaration in memory.
+                    self.flow_control.current_statement = Statement::Function {
+                        name:       name,
+                        args:       args,
+                        statements: statements
                     }
                 }
             },
-            _ => {
-                    let block_jobs: Vec<Pipeline> = self.flow_control
-                        .current_block
-                        .pipelines
-                        .drain(..)
-                        .collect();
-                for pipeline in &block_jobs {
-                    self.run_pipeline(pipeline, false);
+            // Simply executes a provide pipeline, immediately.
+            Statement::Pipelines(mut pipelines) => {
+                // Immediately execute the command as it has no dependents.
+                for pipeline in pipelines.drain(..) {
+                    let _ = self.run_pipeline(&pipeline, false);
                 }
-            }
+            },
+            // At this level, else and else if keywords are forbidden.
+            Statement::ElseIf{..} | Statement::Else => {
+                let stderr = io::stderr();
+                let mut stderr = stderr.lock();
+                let _ = writeln!(stderr, "ion: syntax error: not an if statement");
+            },
+            // Likewise to else and else if, the end keyword does nothing here.
+            Statement::End => {
+                let stderr = io::stderr();
+                let mut stderr = stderr.lock();
+                let _ = writeln!(stderr, "ion: syntax error: no block to end");
+            },
+            _ => {}
         }
-        self.flow_control.current_statement = Statement::Default;
+        Ok(())
     }
 
-    fn handle_pipelines(&mut self, mut pipelines: Vec<Pipeline>, noalias: bool) -> Option<i32> {
-        let mut return_value = None;
-        for pipeline in pipelines.drain(..) {
-            if self.flow_control.collecting_block {
-                let mode = self.flow_control.modes.last().unwrap_or(&flow_control::Mode{value: false}).value;
-                match (mode, self.flow_control.current_statement.clone()) {
-                    (true, Statement::If{..}) | (false, Statement::Else) | (_, Statement::While{..}) |
-                    (_, Statement::For{..}) |(_, Statement::Function{..}) => self.flow_control.current_block.pipelines.push(pipeline),
-                    _ => {}
+    fn on_command(&mut self, command_string: &str) {
+        let mut iterator = StatementSplitter::new(command_string).map(parse);
+
+        // If the value is set to `0`, this means that we don't need to append to an existing
+        // partial statement block in memory, but can read and execute new statements.
+        if self.flow_control.level == 0 {
+            while let Some(statement) = iterator.next() {
+                // Executes all statements that it can, and stores the last remaining partial
+                // statement in memory if needed. We can tell if there is a partial statement
+                // later if the value of `level` is not set to `0`.
+                if let Err(why) = self.execute_toplevel(&mut iterator, statement) {
+                    let stderr = io::stderr();
+                    let mut stderr = stderr.lock();
+                    let _ = writeln!(stderr, "{}", why);
+                    self.flow_control.level = 0;
+                    self.flow_control.current_if_mode = 0;
+                    return
+                }
+            }
+        } else {
+            // Appends the newly parsed statements onto the existing statement stored in memory.
+            match self.flow_control.current_statement {
+                Statement::While{ ref mut statements, .. }
+                    | Statement::For { ref mut statements, .. }
+                    | Statement::Function { ref mut statements, .. } =>
+                {
+                    collect_loops(&mut iterator, statements, &mut self.flow_control.level);
+                },
+                Statement::If { ref mut success, ref mut else_if, ref mut failure, .. } => {
+                    self.flow_control.current_if_mode = match collect_if(&mut iterator, success,
+                        else_if, failure, &mut self.flow_control.level,
+                        self.flow_control.current_if_mode) {
+                            Ok(mode) => mode,
+                            Err(why) => {
+                                let stderr = io::stderr();
+                                let mut stderr = stderr.lock();
+                                let _ = writeln!(stderr, "{}", why);
+                                4
+                            }
+                        };
+                }
+                _ => ()
+            }
+
+            // If this is true, an error occurred during the if statement
+            if self.flow_control.current_if_mode == 4 {
+                self.flow_control.level = 0;
+                self.flow_control.current_if_mode = 0;
+                self.flow_control.current_statement = Statement::Default;
+                return
+            }
+
+            // If the level is set to 0, it means that the statement in memory is finished
+            // and thus is ready for execution.
+            if self.flow_control.level == 0 {
+                // Replaces the `current_statement` with a `Default` value to avoid the
+                // need to clone the value, and clearing it at the same time.
+                let mut replacement = Statement::Default;
+                mem::swap(&mut self.flow_control.current_statement, &mut replacement);
+
+                match replacement {
+                    Statement::While { expression, statements } => {
+                        self.execute_while(expression, statements);
+                    },
+                    Statement::For { variable, values, statements } => {
+                        self.execute_for(&variable, &values, statements);
+                    },
+                    Statement::Function { name, args, statements } => {
+                        self.functions.insert(name.clone(), Function {
+                            name:       name,
+                            args:       args,
+                            statements: statements
+                        });
+                    },
+                    Statement::If { expression, success, else_if, failure } => {
+                        self.execute_if(expression, success, else_if, failure);
+                    }
+                    _ => ()
+                }
+
+                // Capture any leftover statements.
+                while let Some(statement) = iterator.next() {
+                    if let Err(why) = self.execute_toplevel(&mut iterator, statement) {
+                        let stderr = io::stderr();
+                        let mut stderr = stderr.lock();
+                        let _ = writeln!(stderr, "{}", why);
+                        self.flow_control.level = 0;
+                        self.flow_control.current_if_mode = 0;
+                        return
+                    }
                 }
-                return_value = None;
-            } else {
-                return_value = self.run_pipeline(&pipeline, noalias);
             }
         }
-        return_value
     }
 
     /// Sets the history size for the shell context equal to the HISTORY_SIZE shell variable if it
@@ -473,20 +628,17 @@ impl Shell {
                     alias += argument;
                 }
 
-                // Execute each statement within the alias and return the last return value.
                 for statement in StatementSplitter::new(&alias).map(parse) {
-                    if statement.is_flow_control() {
-                        self.flow_control.current_statement = statement.clone();
-                        self.flow_control.collecting_block = true;
-                    }
-
                     match statement {
-                        Statement::End                         => self.handle_end(),
-                        Statement::If{left, right, comparitor} => self.handle_if(left, comparitor, right),
-                        Statement::Pipelines(pipelines)        => {
-                            exit_status = self.handle_pipelines(pipelines, true);
+                        Statement::Pipelines(mut pipelines) => for pipeline in pipelines.drain(..) {
+                            exit_status = self.run_pipeline(&pipeline, true);
                         },
-                        _ => {}
+                        _ => {
+                            exit_status = Some(FAILURE);
+                            let stderr = io::stderr();
+                            let mut stderr = stderr.lock();
+                            let _ = writeln!(stderr, "ion: syntax error: alias only supports pipeline arguments");
+                        }
                     }
                 }
             }
@@ -498,24 +650,23 @@ impl Shell {
                 // Run the 'main' of the command and set exit_status
                 Some((*command.main)(pipeline.jobs[0].args.as_slice(), self))
             // Branch else if -> input == shell function and set the exit_status
-            } else if let Some(function) = self.functions.get(pipeline.jobs[0].command.as_str()).cloned() {
+        } else if let Some(function) = self.functions.get(pipeline.jobs[0].command.as_str()).cloned() {
                 if pipeline.jobs[0].args.len() - 1 == function.args.len() {
                     let mut variables_backup: HashMap<&str, Option<String>> = HashMap::new();
                     for (name, value) in function.args.iter().zip(pipeline.jobs[0].args.iter().skip(1)) {
                         variables_backup.insert(name, self.variables.get_var(name));
                         self.variables.set_var(name, value);
                     }
-                    let mut return_value = None;
-                    for function_pipeline in &function.pipelines {
-                        return_value = self.run_pipeline(function_pipeline, false)
-                    }
+
+                    self.execute_statements(function.statements);
+
                     for (name, value_option) in &variables_backup {
                         match *value_option {
                             Some(ref value) => self.variables.set_var(name, value),
                             None => {self.variables.unset_var(name);},
                         }
                     }
-                    return_value
+                    None
                 } else {
                     let stderr = io::stderr();
                     let mut stderr = stderr.lock();
@@ -830,9 +981,10 @@ impl Command {
 fn main() {
     let mut shell = Shell::default();
     shell.evaluate_init_file();
-    // Clear the history just added by the init file being evaluated.
-    shell.context.history.buffers.clear();
-    shell.set_context_history_from_vars();
+    // NOTE: Remove
+    // // Clear the history just added by the init file being evaluated.
+    // shell.context.history.buffers.clear();
+    // shell.set_context_history_from_vars();
 
     if "1" == shell.variables.get_var_or_empty("HISTORY_FILE_ENABLED") {
         match shell.context.history.load_history() {
diff --git a/src/parser/README.md b/src/parser/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..45f89fec733d7e0623a2372968076d891fcec660
--- /dev/null
+++ b/src/parser/README.md
@@ -0,0 +1,66 @@
+# Ion Shell Parser Logic
+
+This module handles all of the parsing logic within the Ion shell. The following is the strategy currently in use:
+
+1. Parse supplied commands into individual statements using the `StatementSplitter`.
+2. Map each individual statement to their equivalent `Statement` enum using the peg parser.
+3. Later expand shell expressions where required using the `expand_string()` function.
+
+## Parsing Statements
+
+First, inputs received by the shell should be parsed with the `StatementSplitter` in the `statements` module. A statement is any command that is separated by a `;`.
+
+Given the following command:
+
+```ion
+let a = 1; while test $a -lt 100; echo $a; let a += 1; end
+```
+
+The `StatementSplitter` will parse the string and split it into individual statements. This makes the parsing that comes after much easier to manage. Example below, with one statement per line:
+
+```ion
+let a = 1
+while test $a -lt 100
+    echo $a
+    let a += 1
+end
+```
+
+### PEG Parser
+
+Currently, PEG is being used to perform some basic parsing of syntax, but it has a limitation in that it cannot return string references, so at some point it may be replaced for a better solution that can avoid the needless copies.
+
+The PEG parser will read a supplied statement and determine what kind of statement the Statement is -- collecting the required information for that statement and serving it back up as a `Statement` enum. This will later be pattern matched in the actual shell code to determine which code to execute.
+
+#### Pipelines Module
+
+The `pipelines` module is closely related to our `peg` module, in that for a handful of scenarios, such as when parsing `while`, `if`, and regular statements, the `pipelines` module provides a parser that parses pipelines, redirections, and conditional operators in commands, such as the following:
+
+##### Pipelines Example
+
+```ion
+git remote show local | egrep 'tracked|new' | grep -v master | awk '{print $1}'
+```
+
+##### Conditionals Example
+
+```ion
+test -e .git && echo $PWD contains .git directory || echo $PWD does not contain a .git directory
+```
+
+##### Redirection Example
+
+```ion
+cargo build > build.log
+```
+
+#### Loops Module
+
+For loops within Ion work uniquely compared to other shells, in that not only does the `ForExpression` parser parse/expand the supplied expression, but it checks if the expanded expression is either an inclusive or exclusive range, then returns the appropriate `ForExpression`.
+
+### Shell Expansion
+
+This is one of the most important pieces of the parsing puzzle outside of the basic grammar. The purpose of the `shell_expand` module is to supply a generic expansion library that performs all shell expansions throughout the shell.
+
+- The `ForExpression` parser uses the `shell_expand` module to expand the supplied expression before evaluating it.
+- Pipelines are also expanded before
diff --git a/src/parser/grammar.rustpeg b/src/parser/grammar.rustpeg
index 26b75576746f10373299e33982af316917107c1d..381ed31ef9ffb0ddc4cf36b9f2b0e75ab148316f 100644
--- a/src/parser/grammar.rustpeg
+++ b/src/parser/grammar.rustpeg
@@ -1,11 +1,12 @@
 use parser::peg::Pipeline;
 use parser::pipelines;
 use flow_control::Statement;
-use flow_control::Comparitor;
+use flow_control::ElseIf;
 
 #[pub]
 parse_ -> Statement
       = if_
+      / else_if_
       / else_
       / for_
       / while_
@@ -15,7 +16,45 @@ parse_ -> Statement
 
 #[pub]
 if_ -> Statement
-    = whitespace* "if " l:_not_comparitor whitespace c:comparitor whitespace r:_not_comparitor whitespace* { Statement::If{ left: l, comparitor: c, right: r} }
+    = whitespace* "if" whitespace? command:$(.*) {?
+        let mut possible_error = None;
+        let mut pipelines: Vec<Pipeline> = Vec::new();
+
+        pipelines::collect(&mut pipelines, &mut possible_error, command);
+
+        match possible_error {
+            Some(error) => Err(error),
+            None => match pipelines.drain(..).next() {
+                Some(pipeline) => Ok(Statement::If {
+                    expression: pipeline,
+                    success: Vec::new(),
+                    else_if: Vec::new(),
+                    failure: Vec::new()
+                }),
+                None => unreachable!()
+            }
+        }
+    }
+
+#[pub]
+else_if_ -> Statement
+    = whitespace* "else" whitespace? "if" whitespace? command:$(.*) {?
+        let mut possible_error = None;
+        let mut pipelines: Vec<Pipeline> = Vec::new();
+
+        pipelines::collect(&mut pipelines, &mut possible_error, command);
+
+        match possible_error {
+            Some(error) => Err(error),
+            None => match pipelines.drain(..).next() {
+                Some(pipeline) => Ok(Statement::ElseIf(ElseIf {
+                    expression: pipeline,
+                    success:    Vec::new(),
+                })),
+                None => unreachable!()
+            }
+        }
+    }
 
 #[pub]
 else_ -> Statement
@@ -27,7 +66,13 @@ end_ -> Statement
 
 #[pub]
 fn_ -> Statement
-    = whitespace* "fn " n:_name whitespace* args:_args whitespace* { Statement::Function{name: n.to_string(), args: args} }
+    = whitespace* "fn " n:_name whitespace* args:_args whitespace* {
+        Statement::Function {
+            name: n.to_string(),
+            args: args,
+            statements: Vec::new(),
+        }
+    }
 
 _name -> String
       = n:$([A-z]+) { n.to_string() }
@@ -41,7 +86,11 @@ _arg -> String
 #[pub]
 for_ -> Statement
     = whitespace* "for" whitespace? n:_name whitespace? "in" whitespace? expr:$(.*) {
-        Statement::For { variable: n.to_string(), values: expr.to_string() }
+        Statement::For {
+            variable: n.to_string(),
+            values: expr.to_string(),
+            statements: Vec::new(),
+        }
     }
 
 #[pub]
@@ -55,23 +104,15 @@ while_ -> Statement
         match possible_error {
             Some(error) => Err(error),
             None => match pipelines.drain(..).next() {
-                Some(pipeline) => Ok(Statement::While { expression: pipeline }),
+                Some(pipeline) => Ok(Statement::While {
+                    expression: pipeline,
+                    statements: Vec::new()
+                }),
                 None => unreachable!()
             }
         }
     }
 
-comparitor -> Comparitor
-    = "==" { Comparitor::Equal }
-    / "!=" { Comparitor::NotEqual }
-    / "<=" { Comparitor::LessThanOrEqual }
-    / ">=" { Comparitor::GreaterThanOrEqual }
-    / "<"  { Comparitor::LessThan }
-    / ">"  { Comparitor::GreaterThan }
-
-_not_comparitor -> String
-    = !comparitor n:$([^ ]+) { n.to_string() }
-
 #[pub]
 pipelines -> Statement
     = (unused* newline)* [#] .* { Statement::Pipelines(vec![]) }
diff --git a/src/parser/peg.rs b/src/parser/peg.rs
index 2b87569885dedd7e7998866ee748fcb63e936830..f500cfdfb73efd0a6c5ada3494e3cc2107f9a517 100644
--- a/src/parser/peg.rs
+++ b/src/parser/peg.rs
@@ -103,7 +103,8 @@ peg_file! grammar("grammar.rustpeg");
 #[cfg(test)]
 mod tests {
     use super::grammar::*;
-    use flow_control::{Statement, Comparitor};
+    use super::*;
+    use flow_control::Statement;
 
     #[test]
     fn full_script() {
@@ -161,24 +162,20 @@ else
     #[test]
     fn parsing_ifs() {
         // Default case where spaced normally
-        let parsed_if = if_("if 1 == 2").unwrap();
-        let correct_parse = Statement::If{left: "1".to_string(),
-                                        comparitor: Comparitor::Equal,
-                                        right: "2".to_string()};
+        let parsed_if = if_("if test 1 -eq 2").unwrap();
+        let correct_parse = Statement::If {
+            expression: Pipeline::new(
+                vec!(Job::new(
+                    vec!("test".to_owned(), "1".to_owned(), "-eq".to_owned(), "2".to_owned()), JobKind::Last)
+                ), None, None),
+            success: vec!(),
+            else_if: vec!(),
+            failure: vec!()
+        };
         assert_eq!(correct_parse, parsed_if);
 
         // Trailing spaces after final value
-        let parsed_if = if_("if 1 == 2         ").unwrap();
-        let correct_parse = Statement::If{left: "1".to_string(),
-                                        comparitor: Comparitor::Equal,
-                                        right: "2".to_string()};
-        assert_eq!(correct_parse, parsed_if);
-
-        // Default case where spaced normally
-        let parsed_if = if_("if 1 <= 2").unwrap();
-        let correct_parse = Statement::If{left: "1".to_string(),
-                                        comparitor: Comparitor::LessThanOrEqual,
-                                        right: "2".to_string()};
+        let parsed_if = if_("if test 1 -eq 2         ").unwrap();
         assert_eq!(correct_parse, parsed_if);
     }
 
@@ -222,7 +219,11 @@ else
     fn parsing_functions() {
         // Default case where spaced normally
         let parsed_if = fn_("fn bob").unwrap();
-        let correct_parse = Statement::Function{name: "bob".to_string(), args: vec!()};
+        let correct_parse = Statement::Function{
+            name:       "bob".to_string(),
+            args:       vec!(),
+            statements: vec!()
+        };
         assert_eq!(correct_parse, parsed_if);
 
         // Trailing spaces after final value
@@ -235,7 +236,11 @@ else
 
         // Default case where spaced normally
         let parsed_if = fn_("fn bob a b").unwrap();
-        let correct_parse = Statement::Function{name: "bob".to_string(), args: vec!("a".to_string(), "b".to_string())};
+        let correct_parse = Statement::Function{
+            name:       "bob".to_owned(),
+            args:       vec!("a".to_owned(), "b".to_owned()),
+            statements: vec!()
+        };
         assert_eq!(correct_parse, parsed_if);
 
         // Trailing spaces after final value