Merge pull request #14 from gregkatz/master

Added an infinite loop parser and tests.
diff --git a/src/expr.rs b/src/expr.rs
index 04395d3..64e864d 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -337,6 +337,7 @@
 pub mod parsing {
     use super::*;
     use {Ident, Ty};
+    use generics::parsing::lifetime;
     use ident::parsing::ident;
     use lit::parsing::lit;
     use nom::multispace;
@@ -361,7 +362,8 @@
             // TODO: ForLoop
             // TODO: Loop
             // TODO: ForLoop
-            // TODO: Loop
+            |
+            expr_loop
             // TODO: Match
             // TODO: Closure
             |
@@ -549,6 +551,16 @@
         ))
     ));
 
+    named!(expr_loop -> Expr, do_parse!(
+        lt: option!(terminated!(lifetime, punct!(":"))) >>
+        punct!("loop") >>
+        loop_block: block >>
+        (Expr::Loop(
+            Box::new(loop_block),
+            lt.map(|lt| lt.ident),
+        ))
+    ));
+
     named!(expr_block -> Expr, map!(block, |b| Expr::Block(Box::new(b))));
 
     named!(block -> Block, do_parse!(
diff --git a/tests/test_expr.rs b/tests/test_expr.rs
index 75bee8a..587102f 100644
--- a/tests/test_expr.rs
+++ b/tests/test_expr.rs
@@ -13,3 +13,31 @@
 
     assert_eq!(expected, parse_expr(raw).unwrap());
 }
+
+#[test]
+fn test_unnamed_loop() {
+    let block = match parse_expr("{ ( 1, 3, 8 ) }").unwrap() {
+        Expr::Block(b) => b,
+        _ => panic!("Could not run test_unnamed_loop: error in block parse."),
+    };
+
+    let raw = "loop {(1, 3, 8 )}";
+
+    let expected = Expr::Loop(block, None);
+
+    assert_eq!(expected, parse_expr(raw).unwrap());
+}
+
+#[test]
+fn test_named_loop() {
+    let block = match parse_expr("{ ( 1, 5, 9, 11) }").unwrap() {
+        Expr::Block(b) => b,
+        _ => panic!("Could not run named_loop: error in block parse."),
+    };
+
+    let raw = "' test : loop{(1, 5, 9, 11)}";
+
+    let expected = Expr::Loop(block, Some("'test".into()));
+
+    assert_eq!(expected, parse_expr(raw).unwrap());
+}