From bc8bf31b120680f6299e75369653262a320278c5 Mon Sep 17 00:00:00 2001
From: Russel Arbore <russel.jma@gmail.com>
Date: Mon, 11 Sep 2023 10:35:16 -0500
Subject: [PATCH] Refactor out parsing tuple

---
 hercules_ir/src/parse.rs | 89 +++++++++++++++++++++++++++++++---------
 1 file changed, 69 insertions(+), 20 deletions(-)

diff --git a/hercules_ir/src/parse.rs b/hercules_ir/src/parse.rs
index e8438283..5f6b3187 100644
--- a/hercules_ir/src/parse.rs
+++ b/hercules_ir/src/parse.rs
@@ -217,16 +217,7 @@ fn parse_return<'a>(
     ir_text: &'a str,
     context: &RefCell<Context<'a>>,
 ) -> nom::IResult<&'a str, Node> {
-    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, control) = parse_identifier(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, value) = parse_identifier(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, (control, value)) = parse_tuple2(parse_identifier, parse_identifier)(ir_text)?;
     let control = context.borrow_mut().get_node_id(control);
     let value = context.borrow_mut().get_node_id(value);
     Ok((ir_text, Node::Return { control, value }))
@@ -250,16 +241,7 @@ fn parse_constant_node<'a>(
 }
 
 fn parse_add<'a>(ir_text: &'a str, context: &RefCell<Context<'a>>) -> nom::IResult<&'a str, Node> {
-    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, left) = parse_identifier(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, right) = parse_identifier(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, (left, right)) = parse_tuple2(parse_identifier, parse_identifier)(ir_text)?;
     let left = context.borrow_mut().get_node_id(left);
     let right = context.borrow_mut().get_node_id(right);
     Ok((ir_text, Node::Add { left, right }))
@@ -723,6 +705,73 @@ fn parse_identifier<'a>(ir_text: &'a str) -> nom::IResult<&'a str, &'a str> {
     )(ir_text)
 }
 
+fn parse_tuple1<'a, A, AF>(mut parse_a: AF) -> impl FnMut(&'a str) -> nom::IResult<&'a str, (A,)>
+where
+    AF: nom::Parser<&'a str, A, nom::error::Error<&'a str>>,
+{
+    move |ir_text: &'a str| {
+        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, a) = parse_a.parse(ir_text)?;
+        let ir_text = nom::character::complete::multispace0(ir_text)?.0;
+        let ir_text = nom::character::complete::char(')')(ir_text)?.0;
+        Ok((ir_text, (a,)))
+    }
+}
+
+fn parse_tuple2<'a, A, B, AF, BF>(
+    mut parse_a: AF,
+    mut parse_b: BF,
+) -> impl FnMut(&'a str) -> nom::IResult<&'a str, (A, B)>
+where
+    AF: nom::Parser<&'a str, A, nom::error::Error<&'a str>>,
+    BF: nom::Parser<&'a str, B, nom::error::Error<&'a str>>,
+{
+    move |ir_text: &'a str| {
+        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, a) = parse_a.parse(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, b) = parse_b.parse(ir_text)?;
+        let ir_text = nom::character::complete::multispace0(ir_text)?.0;
+        let ir_text = nom::character::complete::char(')')(ir_text)?.0;
+        Ok((ir_text, (a, b)))
+    }
+}
+
+fn parse_tuple3<'a, A, B, C, AF, BF, CF>(
+    mut parse_a: AF,
+    mut parse_b: BF,
+    mut parse_c: CF,
+) -> impl FnMut(&'a str) -> nom::IResult<&'a str, (A, B, C)>
+where
+    AF: nom::Parser<&'a str, A, nom::error::Error<&'a str>>,
+    BF: nom::Parser<&'a str, B, nom::error::Error<&'a str>>,
+    CF: nom::Parser<&'a str, C, nom::error::Error<&'a str>>,
+{
+    move |ir_text: &'a str| {
+        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, a) = parse_a.parse(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, b) = parse_b.parse(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, c) = parse_c.parse(ir_text)?;
+        let ir_text = nom::character::complete::multispace0(ir_text)?.0;
+        let ir_text = nom::character::complete::char(')')(ir_text)?.0;
+        Ok((ir_text, (a, b, c)))
+    }
+}
+
 mod tests {
     #[allow(unused_imports)]
     use super::*;
-- 
GitLab