diff --git a/Cargo.toml b/Cargo.toml
index 09eb39a52ccf513dd274bf57a78be42f628cca03..77c1498a22c9c16ee966bff95a9258b2eb8a9b89 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,7 +16,6 @@ authors = [
 [[bin]]
 name = "ion"
 
-
 [dependencies]
 glob = "0.2"
 liner = "0.1"
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index b4e570c59ded75495c50ca4caba4df56948f836c..0c8c894903c23be018e81fdc1ef9b29803d86ef4 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -9,7 +9,7 @@ pub mod shell_expand;
 mod statements;
 
 pub use self::loops::for_grammar::ForExpression;
-pub use self::statements::StatementSplitter;
+pub use self::statements::{StatementSplitter, StatementError};
 
 /// Takes an argument string as input and expands it.
 pub fn expand_string<'a>(original: &'a str, vars: &Variables, dir_stack: &DirectoryStack) -> Result<String, ExpandErr> {
diff --git a/src/parser/statements.rs b/src/parser/statements.rs
index 8d43fa43fc6e0f4d3e6020da6f0f86f02fac5b54..856b93c2e98e549f763d3c9a901a0162663f2f8b 100644
--- a/src/parser/statements.rs
+++ b/src/parser/statements.rs
@@ -3,23 +3,31 @@ const DQUOTE: u8 = 2;
 const BACKSL: u8 = 4;
 const COMM_1: u8 = 8;
 
+#[derive(Debug, PartialEq)]
+pub enum StatementError {
+    InvalidCharacter(char, usize),
+    UnterminatedSubshell
+}
+
 pub struct StatementSplitter<'a> {
     data:  &'a str,
     read:  usize,
     flags: u8,
+    process_level: u8,
+    // brace_level: u8,
 }
 
 impl<'a> StatementSplitter<'a> {
     pub fn new(data: &'a str) -> StatementSplitter<'a> {
-        StatementSplitter { data: data, read: 0, flags: 0 }
+        StatementSplitter { data: data, read: 0, flags: 0, process_level: 0 }
     }
 }
 
 impl<'a> Iterator for StatementSplitter<'a> {
-    type Item = &'a str;
-    fn next(&mut self) -> Option<&'a str> {
+    type Item = Result<&'a str, StatementError>;
+    fn next(&mut self) -> Option<Result<&'a str, StatementError>> {
         let start = self.read;
-        let mut levels = 0u8;
+        let mut error = None;
         for character in self.data.bytes().skip(self.read) {
             self.read += 1;
             match character {
@@ -28,15 +36,31 @@ impl<'a> Iterator for StatementSplitter<'a> {
                 b'"'  if self.flags & SQUOTE == 0            => self.flags ^= DQUOTE,
                 b'\\' if self.flags & (SQUOTE + DQUOTE) == 0 => self.flags |= BACKSL,
                 b'$'  if self.flags & (SQUOTE + DQUOTE) == 0 => { self.flags |= COMM_1; continue },
-                b'('  if self.flags & COMM_1 != 0            => levels += 1,
-                b')'  if levels > 0                          => levels -= 1,
-                b';'  if (self.flags & (SQUOTE + DQUOTE) == 0) && levels == 0 => {
-                    return Some(self.data[start..self.read-1].trim())
+                b'('  if self.flags & COMM_1 == 0 => {
+                    if error.is_none() {
+                        error = Some(StatementError::InvalidCharacter(character as char, self.read))
+                    }
+                },
+                b'('  if self.flags & COMM_1 != 0 => self.process_level += 1,
+                b')'  if self.process_level == 0 => {
+                    if error.is_none() {
+                        error = Some(StatementError::InvalidCharacter(character as char, self.read))
+                    }
+                },
+                b')' => self.process_level -= 1,
+                b';'  if (self.flags & (SQUOTE + DQUOTE) == 0) && self.process_level == 0 => {
+                    return match error {
+                        Some(error) => Some(Err(error)),
+                        None        => Some(Ok(self.data[start..self.read-1].trim()))
+                    };
                 },
-                b'#' if (self.flags & (SQUOTE + DQUOTE) == 0) && levels == 0 => {
+                b'#' if (self.flags & (SQUOTE + DQUOTE) == 0) && self.process_level == 0 => {
                     let output = self.data[start..self.read-1].trim();
                     self.read = self.data.len();
-                    return Some(output);
+                    return match error {
+                        Some(error) => Some(Err(error)),
+                        None        => Some(Ok(output))
+                    };
                 },
                 _ => ()
             }
@@ -47,16 +71,31 @@ impl<'a> Iterator for StatementSplitter<'a> {
             None
         } else {
             self.read = self.data.len();
-            Some(self.data[start..].trim())
+            match error {
+                Some(error) => Some(Err(error)),
+                None if self.process_level != 0 => Some(Err(StatementError::UnterminatedSubshell)),
+                None => Some(Ok(self.data[start..].trim()))
+            }
         }
     }
 }
 
+#[test]
+fn statements_with_syntax_errors() {
+    let command = "echo (echo one); echo $((echo one); echo ) two; echo $(echo one";
+    let results = StatementSplitter::new(command).collect::<Vec<Result<&str, StatementError>>>();
+    assert_eq!(results.len(), 4);
+    assert_eq!(results[0], Err(StatementError::InvalidCharacter('(', 6)));
+    assert_eq!(results[1], Err(StatementError::InvalidCharacter('(', 25)));
+    assert_eq!(results[2], Err(StatementError::InvalidCharacter(')', 42)));
+    assert_eq!(results[3], Err(StatementError::UnterminatedSubshell));
+}
+
 #[test]
 fn statements_with_processes() {
     let command = "echo $(seq 1 10); echo $(seq 1 10)";
     for statement in StatementSplitter::new(command) {
-        assert_eq!(statement, "echo $(seq 1 10)");
+        assert_eq!(statement, Ok("echo $(seq 1 10)"));
     }
 }
 
@@ -64,37 +103,37 @@ fn statements_with_processes() {
 fn statements_process_with_statements() {
     let command = "echo $(seq 1 10; seq 1 10)";
     for statement in StatementSplitter::new(command) {
-        assert_eq!(statement, command);
+        assert_eq!(statement, Ok(command));
     }
 }
 
 #[test]
 fn statements_with_quotes() {
     let command = "echo \"This ;'is a test\"; echo 'This ;\" is also a test'";
-    let results = StatementSplitter::new(command).collect::<Vec<&str>>();
+    let results = StatementSplitter::new(command).collect::<Vec<Result<&str, StatementError>>>();
     assert_eq!(results.len(), 2);
-    assert_eq!(results[0], "echo \"This ;'is a test\"");
-    assert_eq!(results[1], "echo 'This ;\" is also a test'");
+    assert_eq!(results[0], Ok("echo \"This ;'is a test\""));
+    assert_eq!(results[1], Ok("echo 'This ;\" is also a test'"));
 }
 
 #[test]
 fn statements_with_comments() {
     let command = "echo $(echo one # two); echo three # four";
-    let results = StatementSplitter::new(command).collect::<Vec<&str>>();
+    let results = StatementSplitter::new(command).collect::<Vec<Result<&str, StatementError>>>();
     assert_eq!(results.len(), 2);
-    assert_eq!(results[0], "echo $(echo one # two)");
-    assert_eq!(results[1], "echo three");
+    assert_eq!(results[0], Ok("echo $(echo one # two)"));
+    assert_eq!(results[1], Ok("echo three"));
 }
 
 #[test]
 fn statements_with_process_recursion() {
     let command = "echo $(echo one $(echo two) three)";
-    let results = StatementSplitter::new(command).collect::<Vec<&str>>();
+    let results = StatementSplitter::new(command).collect::<Vec<Result<&str, StatementError>>>();
     assert_eq!(results.len(), 1);
-    assert_eq!(results[0], command);
+    assert_eq!(results[0], Ok(command));
 
     let command = "echo $(echo $(echo one; echo two); echo two)";
-    let results = StatementSplitter::new(command).collect::<Vec<&str>>();
+    let results = StatementSplitter::new(command).collect::<Vec<Result<&str, StatementError>>>();
     assert_eq!(results.len(), 1);
-    assert_eq!(results[0], command);
+    assert_eq!(results[0], Ok(command));
 }
diff --git a/src/shell/flow.rs b/src/shell/flow.rs
index 80a1abf54a9e15ceadf58197b098a51feccd7170..eabd2adbacc47de1a5e132401a412c6221d84cbe 100644
--- a/src/shell/flow.rs
+++ b/src/shell/flow.rs
@@ -4,7 +4,7 @@ use status::*;
 use super::Shell;
 
 use flow_control::{ElseIf, Function, Statement, collect_loops, collect_if};
-use parser::{ForExpression, StatementSplitter};
+use parser::{ForExpression, StatementSplitter, StatementError};
 use parser::peg::{parse, Pipeline};
 
 pub trait FlowLogic {
@@ -20,7 +20,25 @@ pub trait FlowLogic {
 
 impl<'a> FlowLogic for Shell<'a> {
     fn on_command(&mut self, command_string: &str) {
-        let mut iterator = StatementSplitter::new(command_string).map(parse);
+        let mut iterator = StatementSplitter::new(command_string).filter_map(|statement| {
+            match statement {
+                Ok(statement) => Some(statement),
+                Err(err) => {
+                    let stderr = io::stderr();
+                    match err {
+                        StatementError::InvalidCharacter(character, position) => {
+                            let _ = writeln!(stderr.lock(),
+                                "ion: syntax error: '{}' at position {} is out of place",
+                                character, position);
+                        },
+                        StatementError::UnterminatedSubshell => {
+                            let _ = writeln!(stderr.lock(), "ion: syntax error: unterminated subshell");
+                        }
+                    }
+                    None
+                }
+            }
+        }).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.
diff --git a/src/shell/mod.rs b/src/shell/mod.rs
index 9b76840be7bbe7d338db25c0f58a6dad5f8911ef..f21e603a079f4be13173ff934259fa3743450027 100644
--- a/src/shell/mod.rs
+++ b/src/shell/mod.rs
@@ -25,7 +25,7 @@ use variables::Variables;
 use status::*;
 use pipe::execute_pipeline;
 use parser::shell_expand::ExpandErr;
-use parser::{expand_string, StatementSplitter};
+use parser::{expand_string, StatementError, StatementSplitter};
 use parser::peg::{parse, Pipeline};
 
 /// This struct will contain all of the data structures related to this
@@ -154,7 +154,8 @@ impl<'a> Shell<'a> {
                 } else {
                     match File::open(&arg) {
                         Ok(mut file) => {
-                            let mut command_list = String::new();
+                            let capacity = file.metadata().ok().map_or(0, |x| x.len());
+                            let mut command_list = String::with_capacity(capacity as usize);
                             match file.read_to_string(&mut command_list) {
                                 Ok(_) => {
                                     for command in command_list.lines() {
@@ -294,7 +295,25 @@ impl<'a> Shell<'a> {
                     alias += argument;
                 }
 
-                for statement in StatementSplitter::new(&alias).map(parse) {
+                for statement in StatementSplitter::new(&alias).filter_map(|statement| {
+                    match statement {
+                        Ok(statement) => Some(statement),
+                        Err(err) => {
+                            let stderr = io::stderr();
+                            match err {
+                                StatementError::InvalidCharacter(character, position) => {
+                                    let _ = writeln!(stderr.lock(),
+                                        "ion: syntax error: '{}' at position {} is out of place",
+                                        character, position);
+                                },
+                                StatementError::UnterminatedSubshell => {
+                                    let _ = writeln!(stderr.lock(), "ion: syntax error: unterminated subshell");
+                                }
+                            }
+                            None
+                        }
+                    }
+                }).map(parse) {
                     match statement {
                         Statement::Pipelines(mut pipelines) => for mut pipeline in pipelines.drain(..) {
                             exit_status = self.run_pipeline(&mut pipeline, true);
@@ -316,7 +335,7 @@ impl<'a> Shell<'a> {
                 // 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)) {