Comment parsing
diff --git a/src/space.rs b/src/space.rs
new file mode 100644
index 0000000..ae0036d
--- /dev/null
+++ b/src/space.rs
@@ -0,0 +1,83 @@
+#![cfg(feature = "parsing")]
+
+use nom::IResult;
+use unicode_xid::UnicodeXID;
+
+pub fn whitespace(input: &str) -> IResult<&str, ()> {
+    if input.is_empty() {
+        return IResult::Error;
+    }
+
+    let mut start = 0;
+    let mut chars = input.char_indices();
+    while let Some((i, ch)) = chars.next() {
+        let s = &input[start + i..];
+        if ch == '/' {
+            if s.starts_with("//")
+                    && (!s.starts_with("///") || s.starts_with("////"))
+                    && !s.starts_with("//!") {
+                if let Some(len) = s.find('\n') {
+                    start += i + len + 1;
+                    chars = input[start..].char_indices();
+                    continue;
+                }
+                break;
+            } else if s.starts_with("/*")
+                    && !s.starts_with("/**")
+                    && !s.starts_with("/*!") {
+                match block_comment(s) {
+                    IResult::Done(_, com) => {
+                        start += i + com.len();
+                        chars = input[start..].char_indices();
+                        continue;
+                    }
+                    IResult::Error => {
+                        return IResult::Error;
+                    }
+                }
+            }
+        }
+        if !ch.is_whitespace() {
+            return if start + i > 0 {
+                IResult::Done(s, ())
+            } else {
+                IResult::Error
+            };
+        }
+    }
+    IResult::Done("", ())
+}
+
+pub fn block_comment(input: &str) -> IResult<&str, &str> {
+    if !input.starts_with("/*") {
+        return IResult::Error;
+    }
+
+    let mut depth = 0;
+    let mut chars = input.char_indices();
+    while let Some((i, _)) = chars.next() {
+        let s = &input[i..];
+        if s.starts_with("/*") {
+            depth += 1;
+            chars.next(); // eat '*'
+        } else if s.starts_with("*/") {
+            depth -= 1;
+            if depth == 0 {
+                return IResult::Done(&input[i + 2..], &input[..i + 2]);
+            }
+            chars.next(); // eat '/'
+        }
+    }
+    IResult::Error
+}
+
+pub fn word_break(input: &str) -> IResult<&str, ()> {
+    match input.chars().next() {
+        Some(ch) if UnicodeXID::is_xid_continue(ch) => {
+            IResult::Error
+        }
+        Some(_) | None => {
+            IResult::Done(input, ())
+        }
+    }
+}