diff --git a/examples/tmp.rs b/examples/tmp.rs
index ec7393d6cf7d267561468839a8a9a05f1ff2f81e..c84931cd0b29054a2e8ad0c97a852dcb820257db 100644
--- a/examples/tmp.rs
+++ b/examples/tmp.rs
@@ -1,120 +1,7 @@
 extern crate nom;
 
-use std::iter::Peekable;
-use std::slice::Iter;
 
-use nom::{
-    branch::alt,
-    bytes::complete::tag,
-    character::complete::char,
-    character::complete::{digit1, multispace0},
-    combinator::{cut, map},
-    error::ParseError,
-    multi::many1,
-    sequence::{delimited, preceded},
-    IResult,
-};
-
-use crust::ast::{Op, Expr};
-
-
-pub fn parse_i32(i: &str) -> IResult<&str, i32> {
-    map(digit1, |digit_str: &str| digit_str.parse::<i32>().unwrap())(i)
-}
-
-fn parse_op(i: &str) -> IResult<&str, Op> {
-    alt((
-        map(tag("=="), |_| Op::Eq),
-        map(tag("!="), |_| Op::Neq),
-        map(tag("**"), |_| Op::Pow),
-        map(tag("&&"), |_| Op::And),
-        map(tag("||"), |_| Op::Or),
-        map(tag("+"), |_| Op::Add),
-        map(tag("-"), |_| Op::Sub),
-        map(tag("*"), |_| Op::Mul),
-        map(tag("/"), |_| Op::Div),
-        map(tag("!"), |_| Op::Not),
-    ))(i)
-}
-
-#[derive(Debug, Clone, PartialEq)]
-pub enum Token {
-    Num(i32),
-    Par(Vec<Token>),
-    Op(Op),
-}
-
-fn parse_terminal(i: &str) -> IResult<&str, Token> {
-    alt((
-        map(parse_i32, |v| Token::Num(v)),
-        map(parse_par(parse_tokens), |tokens| Token::Par(tokens)),
-    ))(i)
-}
-
-fn parse_token(i: &str) -> IResult<&str, Token> {
-    preceded(
-        multispace0,
-        alt((map(parse_op, |op| Token::Op(op)), parse_terminal)),
-    )(i)
-}
-
-fn parse_tokens(i: &str) -> IResult<&str, Vec<Token>> {
-    many1(parse_token)(i)
-}
-
-fn compute_atom(t: &mut Peekable<Iter<Token>>) -> Expr {
-    match t.next() {
-        Some(Token::Num(i)) => Expr::Num(*i),
-        Some(Token::Par(v)) => climb(&mut v.iter().peekable(), 0),
-        Some(Token::Op(op)) => Expr::UnaryOp(*op, Box::new(climb(t, 4))), // assume highest precedence
-        _ => panic!("error in compute atom"),
-    }
-}
-
-fn climb(t: &mut Peekable<Iter<Token>>, min_prec: u8) -> Expr {
-    let mut result = compute_atom(t);
-
-    loop {
-        match t.peek() {
-            Some(Token::Op(op)) => {
-                let (prec, ass) = get_prec(op);
-                if prec < min_prec {
-                    break;
-                };
-                let next_prec = prec
-                    + match ass {
-                        Ass::Left => 1,
-                        _ => 0,
-                    };
-                t.next();
-                let rhs = climb(t, next_prec);
-                result = Expr::BinOp(*op, Box::new(result), Box::new(rhs))
-            }
-            _ => {
-                break;
-            }
-        }
-    }
-    result
-}
-
-fn test(s: &str, v: i32) {
-    match parse_tokens(s) {
-        Ok(("", t)) => {
-            let mut t = t.iter().peekable();
-            println!("{:?}", &t);
-            let e = climb(&mut t, 0);
-            println!("{:?}", &e);
-            println!("eval {} {}", math_eval(&e), v);
-            assert_eq!(math_eval(&e), v);
-        }
-        Ok((s, t)) => println!(
-            "parse incomplete, \n parsed tokens \t{:?}, \n remaining \t{:?}",
-            t, s
-        ),
-        Err(err) => println!("{:?}", err),
-    }
-}
+use crust::parse::test;
 
 fn main() {
     test("- -1 + + 1", - -1 + 1);  // rust does not allow + as a unary op (I do ;)
@@ -127,59 +14,4 @@ fn main() {
     test("1*2+3+3*21-a12+2", 1 * 2 + 3 + 3 * 21 - 12 + 2);
 }
 
-// helpers
-fn parse_par<'a, O, F, E>(
-    inner: F,
-) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
-where
-    F: Fn(&'a str) -> IResult<&'a str, O, E>,
-    E: ParseError<&'a str>,
-{
-    // delimited allows us to split up the input
-    // cut allwos us to consume the input (and prevent backtracking)
-    delimited(char('('), preceded(multispace0, inner), cut(char(')')))
-}
-
-fn math_eval(e: &Expr) -> i32 {
-    match e {
-        Expr::Num(i) => *i,
-        Expr::BinOp(op, l, r) => {
-            let lv = math_eval(l);
-            let rv = math_eval(r);
-            match op {
-                Op::Add => lv + rv,
-                Op::Sub => lv - rv,
-                Op::Mul => lv * rv,
-                Op::Div => lv / rv,
-                Op::Pow => lv.pow(rv as u32),
-                _ => unimplemented!(),
-            }
-        }
-        Expr::UnaryOp(op, e) => {
-            let e = math_eval(e);
-            match op {
-                Op::Add => e,
-                Op::Sub => -e,
-                _ => unimplemented!(),
-            }
-        }
-        _ => unimplemented!(),
-    }
-}
 
-#[derive(Debug, Copy, Clone, PartialEq)]
-enum Ass {
-    Left,
-    Right,
-}
-
-fn get_prec(op: &Op) -> (u8, Ass) {
-    match op {
-        Op::Add => (1, Ass::Left),
-        Op::Sub => (1, Ass::Left),
-        Op::Mul => (2, Ass::Left),
-        Op::Div => (2, Ass::Left),
-        Op::Pow => (3, Ass::Right),
-        _ => unimplemented!(),
-    }
-}
diff --git a/src/ast.rs b/src/ast.rs
index 3c2f8b41459bac8bfe773ef894b26a9499f4fa64..bc4464e33e5158c2db7a2431dec5a2a71ed7f55d 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -2,7 +2,7 @@
 
 use nom_locate::LocatedSpan;
 
-type Span<'a> = LocatedSpan<&'a str>;
+pub type Span<'a> = LocatedSpan<&'a str>;
 
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub enum Op {
@@ -21,13 +21,13 @@ pub enum Op {
 type SpanOp<'a> = (Span<'a>, Op);
 
 #[derive(Debug, Clone, PartialEq)]
-pub enum Expr {
+pub enum Expr<'a> {
     Num(i32),
-    Par(Box<Expr>),
+    Par(Box<SpanExpr<'a>>),
     // Identifier
     // Function application
-    BinOp(Op, Box<Expr>, Box<Expr>),
-    UnaryOp(Op, Box<Expr>),
+    BinOp(Op, Box<SpanExpr<'a>>, Box<SpanExpr<'a>>),
+    UnaryOp(Op, Box<SpanExpr<'a>>),
 }
 
-type SpanExpr<'a> = (Span<'a>, Expr);
+pub type SpanExpr<'a> = (Span<'a>, Expr<'a>);
diff --git a/src/lib.rs b/src/lib.rs
index 95787c26b88a62b43f78980ce41580778a495ae1..b5afecafe3d0a66ea3b66ae31359b41646bb88aa 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,4 @@
 // lib
 
-pub mod ast;
\ No newline at end of file
+pub mod ast;
+pub mod parse;
diff --git a/src/parse.rs b/src/parse.rs
new file mode 100644
index 0000000000000000000000000000000000000000..77e8edc0807348a39b4e79deb9bf096086e193c6
--- /dev/null
+++ b/src/parse.rs
@@ -0,0 +1,183 @@
+extern crate nom;
+
+use std::iter::Peekable;
+use std::slice::Iter;
+
+use nom::{
+    branch::alt,
+    bytes::complete::tag,
+    character::complete::char,
+    character::complete::{digit1, multispace0},
+    combinator::{cut, map},
+    error::ParseError,
+    multi::many1,
+    sequence::{delimited, preceded},
+    IResult,
+};
+
+use crate::ast::{Expr, Op, Span, SpanExpr};
+
+pub fn parse_i32(i: Span) -> IResult<Span, (Span, i32)> {
+    map(digit1, |digit_str: Span| {
+        (digit_str, digit_str.fragment.parse::<i32>().unwrap())
+    })(i)
+}
+
+fn parse_op(i: Span) -> IResult<Span, (Span, Op)> {
+    alt((
+        map(tag("=="), |s| (s, Op::Eq)),
+        map(tag("!="), |s| (s, Op::Neq)),
+        map(tag("**"), |s| (s, Op::Pow)),
+        map(tag("&&"), |s| (s, Op::And)),
+        map(tag("||"), |s| (s, Op::Or)),
+        map(tag("+"), |s| (s, Op::Add)),
+        map(tag("-"), |s| (s, Op::Sub)),
+        map(tag("*"), |s| (s, Op::Mul)),
+        map(tag("/"), |s| (s, Op::Div)),
+        map(tag("!"), |s| (s, Op::Not)),
+    ))(i)
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum Token<'a> {
+    Num(i32),
+    Par(Vec<SpanToken<'a>>),
+    Op(Op),
+}
+
+type SpanToken<'a> = (Span<'a>, Token<'a>);
+
+fn parse_terminal(i: Span) -> IResult<Span, SpanToken> {
+    alt((
+        map(parse_i32, |(s, v)| (s, Token::Num(v))),
+        map(parse_par(parse_tokens), |(s, tokens)| {
+            (s, Token::Par(tokens))
+        }),
+    ))(i)
+}
+
+fn parse_token(i: Span) -> IResult<Span, SpanToken> {
+    preceded(
+        multispace0,
+        alt((map(parse_op, |(s, op)| (s, Token::Op(op))), parse_terminal)),
+    )(i)
+}
+
+// I think the outer span is wrong
+fn parse_tokens(i: Span) -> IResult<Span, (Span, Vec<SpanToken>)> {
+    map(many1(parse_token), |tokens| (i, tokens))(i)
+}
+
+fn compute_atom<'a>(t: &mut Peekable<Iter<SpanToken<'a>>>) -> SpanExpr<'a> {
+    match t.next() {
+        Some((s, Token::Num(i))) => (*s, Expr::Num(*i)),
+        Some((_, Token::Par(v))) => climb(&mut v.iter().peekable(), 0),
+        Some((s, Token::Op(op))) => (*s, Expr::UnaryOp(*op, Box::new(climb(t, 4)))), // assume highest precedence
+        _ => panic!("error in compute atom"),
+    }
+}
+
+fn climb<'a>(
+    t: &mut Peekable<Iter<SpanToken<'a>>>,
+    min_prec: u8,
+) -> SpanExpr<'a> {
+    let mut result: SpanExpr = compute_atom(t);
+
+    loop {
+        match t.peek() {
+            Some((s, Token::Op(op))) => {
+                let (prec, ass) = get_prec(op);
+                if prec < min_prec {
+                    break;
+                };
+                let next_prec = prec
+                    + match ass {
+                        Ass::Left => 1,
+                        _ => 0,
+                    };
+                t.next();
+                let rhs = climb(t, next_prec);
+                result = (*s, Expr::BinOp(*op, Box::new(result), Box::new(rhs)))
+            }
+            _ => {
+                break;
+            }
+        }
+    }
+    result
+}
+
+pub fn test(s: &str, v: i32) {
+    match parse_tokens(Span::new(s)) {
+        Ok((Span { fragment: "", .. }, (_, t))) => {
+            let mut t = t.iter().peekable();
+            println!("{:?}", &t);
+            let e = climb(&mut t, 0);
+            println!("{:?}", &e);
+            println!("eval {} {}", math_eval(&e), v);
+            assert_eq!(math_eval(&e), v);
+        }
+        Ok((s, t)) => println!(
+            "parse incomplete, \n parsed tokens \t{:?}, \n remaining \t{:?}",
+            t, s
+        ),
+        Err(err) => println!("{:?}", err),
+    }
+}
+
+// helpers
+fn parse_par<'a, O, F, E>(
+    inner: F,
+) -> impl Fn(Span<'a>) -> IResult<Span<'a>, O, E>
+where
+    F: Fn(Span<'a>) -> IResult<Span<'a>, O, E>,
+    E: ParseError<Span<'a>>,
+{
+    // delimited allows us to split up the input
+    // cut allwos us to consume the input (and prevent backtracking)
+    delimited(char('('), preceded(multispace0, inner), cut(char(')')))
+}
+
+fn math_eval(e: &SpanExpr) -> i32 {
+    match e.clone().1 {
+        Expr::Num(i) => i,
+        Expr::BinOp(op, l, r) => {
+            let lv = math_eval(&l);
+            let rv = math_eval(&r);
+            match op {
+                Op::Add => lv + rv,
+                Op::Sub => lv - rv,
+                Op::Mul => lv * rv,
+                Op::Div => lv / rv,
+                Op::Pow => lv.pow(rv as u32),
+                _ => unimplemented!(),
+            }
+        }
+        Expr::UnaryOp(op, e) => {
+            let e = math_eval(&e);
+            match op {
+                Op::Add => e,
+                Op::Sub => -e,
+                _ => unimplemented!(),
+            }
+        }
+        _ => unimplemented!(),
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum Ass {
+    Left,
+    Right,
+}
+
+fn get_prec(op: &Op) -> (u8, Ass) {
+    match op {
+        Op::Add => (1, Ass::Left),
+        Op::Sub => (1, Ass::Left),
+        Op::Mul => (2, Ass::Left),
+        Op::Div => (2, Ass::Left),
+        Op::Pow => (3, Ass::Right),
+        _ => unimplemented!(),
+    }
+}