diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs
index 2589e0bd0d45cc735da800c3a012104fa8bcf9e2..005de05091789f50b4b48a4508d4230d15625a55 100644
--- a/hercules_ir/src/ir.rs
+++ b/hercules_ir/src/ir.rs
@@ -1,13 +1,13 @@
 extern crate ordered_float;
 
-#[derive(Clone)]
+#[derive(Debug, Clone)]
 pub struct Module {
     pub functions: Vec<Function>,
     pub types: Vec<Type>,
     pub constants: Vec<Constant>,
 }
 
-#[derive(Clone)]
+#[derive(Debug, Clone)]
 pub struct Function {
     pub name: String,
     pub param_types: Vec<TypeID>,
@@ -15,7 +15,7 @@ pub struct Function {
     pub nodes: Vec<Node>,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Type {
     Control(u64),
     Integer8,
@@ -26,7 +26,7 @@ pub enum Type {
     Float64,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Constant {
     Integer8(u8),
     Integer16(u16),
@@ -36,7 +36,7 @@ pub enum Constant {
     Float64(ordered_float::OrderedFloat<f64>),
 }
 
-#[derive(Clone)]
+#[derive(Debug, Clone)]
 pub enum Node {
     Start,
     Region {
@@ -93,7 +93,7 @@ pub enum Node {
     },
 }
 
-#[derive(Clone, Copy)]
+#[derive(Debug, Clone, Copy)]
 pub struct FunctionID(u32);
 
 impl FunctionID {
@@ -106,7 +106,7 @@ impl FunctionID {
     }
 }
 
-#[derive(Clone, Copy)]
+#[derive(Debug, Clone, Copy)]
 pub struct NodeID(u32);
 
 impl NodeID {
@@ -119,7 +119,7 @@ impl NodeID {
     }
 }
 
-#[derive(Clone, Copy)]
+#[derive(Debug, Clone, Copy)]
 pub struct ConstantID(u32);
 
 impl ConstantID {
@@ -132,7 +132,7 @@ impl ConstantID {
     }
 }
 
-#[derive(Clone, Copy)]
+#[derive(Debug, Clone, Copy)]
 pub struct TypeID(u32);
 
 impl TypeID {
diff --git a/hercules_ir/src/parse.rs b/hercules_ir/src/parse.rs
index e854ddb14536eeea34738ce7a7ba93ba93e308f1..e70e608ae4b2213fef7497cec3ebf28568dd1518 100644
--- a/hercules_ir/src/parse.rs
+++ b/hercules_ir/src/parse.rs
@@ -16,6 +16,18 @@ struct Context<'a> {
     interned_constants: HashMap<Constant, ConstantID>,
 }
 
+impl<'a> Context<'a> {
+    fn get_node_id(&mut self, name: &'a str) -> NodeID {
+        if let Some(id) = self.node_ids.get(name) {
+            *id
+        } else {
+            let id = NodeID::new(self.node_ids.len());
+            self.node_ids.insert(name, id);
+            id
+        }
+    }
+}
+
 fn parse_module<'a>(ir_text: &'a str, mut context: Context<'a>) -> nom::IResult<&'a str, Module> {
     let (rest, functions) =
         nom::combinator::all_consuming(nom::multi::many0(|x| parse_function(x, &mut context)))(
@@ -47,22 +59,25 @@ fn parse_function<'a>(
     let ir_text = nom::character::complete::multispace0(ir_text)?.0;
     let ir_text = nom::bytes::complete::tag("fn")(ir_text)?.0;
     let ir_text = nom::character::complete::multispace0(ir_text)?.0;
-    let (ir_text, function_name) = nom::character::complete::alphanumeric0(ir_text)?;
+    let (ir_text, function_name) = nom::character::complete::alphanumeric1(ir_text)?;
     let ir_text = nom::character::complete::char('(')(ir_text)?.0;
     let (ir_text, params) = nom::multi::separated_list0(
         nom::character::complete::char(','),
         nom::sequence::tuple((
+            nom::character::complete::multispace0,
             nom::character::complete::alphanumeric1,
             nom::character::complete::multispace0,
             nom::character::complete::char(':'),
             nom::character::complete::multispace0,
             |x| parse_type(x, context),
+            nom::character::complete::multispace0,
         )),
     )(ir_text)?;
+    context.node_ids.insert("start", NodeID::new(0));
     for param in params.iter() {
         context
             .node_ids
-            .insert(param.0, NodeID::new(context.node_ids.len()));
+            .insert(param.1, NodeID::new(context.node_ids.len()));
     }
     let ir_text = nom::character::complete::char(')')(ir_text)?.0;
     let ir_text = nom::character::complete::multispace0(ir_text)?.0;
@@ -74,13 +89,15 @@ fn parse_function<'a>(
         fixed_nodes[context.node_ids.remove(name).unwrap().idx()] = node;
     }
     for (_, id) in context.node_ids.iter() {
-        fixed_nodes[id.idx()] = Node::Parameter { index: id.idx() }
+        if id.idx() != 0 {
+            fixed_nodes[id.idx()] = Node::Parameter { index: id.idx() }
+        }
     }
     Ok((
         ir_text,
         Function {
             name: String::from(function_name),
-            param_types: params.into_iter().map(|x| x.4).collect(),
+            param_types: params.into_iter().map(|x| x.5).collect(),
             return_type,
             nodes: fixed_nodes,
         },
@@ -91,10 +108,73 @@ fn parse_node<'a>(
     ir_text: &'a str,
     context: &mut Context<'a>,
 ) -> nom::IResult<&'a str, (&'a str, Node)> {
-    todo!()
+    let ir_text = nom::character::complete::multispace0(ir_text)?.0;
+    let (ir_text, node_name) = nom::character::complete::alphanumeric1(ir_text)?;
+    let ir_text = nom::character::complete::multispace0(ir_text)?.0;
+    let ir_text = nom::character::complete::char('=')(ir_text)?.0;
+    let ir_text = nom::character::complete::multispace0(ir_text)?.0;
+    let (ir_text, node_kind) = nom::character::complete::alphanumeric1(ir_text)?;
+    let (ir_text, node) = match node_kind {
+        "return" => {
+            let (ir_text, comps) = nom::sequence::tuple((
+                nom::character::complete::multispace0,
+                nom::character::complete::char('('),
+                nom::character::complete::multispace0,
+                nom::character::complete::alphanumeric1,
+                nom::character::complete::multispace0,
+                nom::character::complete::char(','),
+                nom::character::complete::multispace0,
+                nom::character::complete::alphanumeric1,
+                nom::character::complete::multispace0,
+                nom::character::complete::char(')'),
+            ))(ir_text)?;
+            let control_id = context.get_node_id(comps.3);
+            let value_id = context.get_node_id(comps.7);
+            (
+                ir_text,
+                Node::Return {
+                    control: control_id,
+                    value: value_id,
+                },
+            )
+        }
+        "add" => {
+            let (ir_text, comps) = nom::sequence::tuple((
+                nom::character::complete::multispace0,
+                nom::character::complete::char('('),
+                nom::character::complete::multispace0,
+                nom::character::complete::alphanumeric1,
+                nom::character::complete::multispace0,
+                nom::character::complete::char(','),
+                nom::character::complete::multispace0,
+                nom::character::complete::alphanumeric1,
+                nom::character::complete::multispace0,
+                nom::character::complete::char(','),
+                nom::character::complete::multispace0,
+                nom::character::complete::alphanumeric1,
+                nom::character::complete::multispace0,
+                nom::character::complete::char(')'),
+            ))(ir_text)?;
+            let control_id = context.get_node_id(comps.3);
+            let left_id = context.get_node_id(comps.7);
+            let right_id = context.get_node_id(comps.11);
+            (
+                ir_text,
+                Node::Add {
+                    control: control_id,
+                    left: left_id,
+                    right: right_id,
+                },
+            )
+        }
+        _ => todo!(),
+    };
+    context.get_node_id(node_name);
+    Ok((ir_text, (node_name, node)))
 }
 
 fn parse_type<'a>(ir_text: &'a str, context: &mut Context<'a>) -> nom::IResult<&'a str, TypeID> {
+    let ir_text = nom::character::complete::multispace0(ir_text)?.0;
     let (ir_text, ty) =
         nom::combinator::map(nom::bytes::complete::tag("i32"), |_| Type::Integer32)(ir_text)?;
     let id = if let Some(id) = context.interned_types.get(&ty) {
@@ -120,6 +200,8 @@ mod tests {
 
     #[test]
     fn parse_ir1() {
-        parse("fn add(x: i32, y: i32) -> i32 r = return(z) z = add(start, x, y)");
+        let module =
+            parse("fn add(x: i32, y: i32) -> i32 r = return(start, z) z = add(start, x, y)");
+        println!("{:?}", module);
     }
 }