from upstream here: https://gitlab.com/davidbittner/ansi-parser/-/merge_requests/13

diff --git a/Cargo.toml b/Cargo.toml
index ba9cdfc..2465b6f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,7 +22,7 @@ license = "MPL-2.0"
 version = "0.7"
 
 [dependencies.nom]
-version = "4"
+version = "7"
 default-features = false
 
 [features]
diff --git a/src/parsers.rs b/src/parsers.rs
index 7880d50..76aef6a 100644
--- a/src/parsers.rs
+++ b/src/parsers.rs
@@ -3,264 +3,196 @@ mod tests;
 
 use crate::AnsiSequence;
 
-use core::convert::TryInto;
 use heapless::Vec;
-use nom::*;
+use nom::branch::alt;
+use nom::bytes::complete::tag;
+use nom::character::complete::{digit0, digit1};
+use nom::combinator::{map, map_res, opt, value};
+use nom::sequence::{delimited, preceded, tuple};
+use nom::IResult;
 
 macro_rules! tag_parser {
     ($sig:ident, $tag:expr, $ret:expr) => {
-        named!(
-            $sig<&str, AnsiSequence>,
-            do_parse!(
-                tag!($tag) >>
-                ($ret)
-            )
-        );
-    }
+        fn $sig(input: &str) -> IResult<&str, AnsiSequence> {
+            value($ret, tag($tag))(input)
+        }
+    };
 }
 
-named!(
-    parse_int<&str, u32>,
-    map_res!(
-        nom::digit,
-        |s: &str| s.parse::<u32>()
-    )
-);
+fn parse_u32(input: &str) -> IResult<&str, u32> {
+    map_res(digit1, |s: &str| s.parse::<u32>())(input)
+}
+
+fn parse_u8(input: &str) -> IResult<&str, u8> {
+    map_res(digit1, |s: &str| s.parse::<u8>())(input)
+}
 
 // TODO kind of ugly, would prefer to pass in the default so we could use it for
 // all escapes with defaults (not just those that default to 1).
-named!(
-    parse_def_cursor_int<&str, u32>,
-    map!(
-        nom::digit0,
-        |s: &str| s.parse::<u32>().unwrap_or(1)
-    )
-);
-
-named!(
-    cursor_pos<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")               >>
-        x: parse_def_cursor_int >>
-        opt!(tag!(";"))         >>
-        y: parse_def_cursor_int >>
-        alt!(
-            tag!("H") |
-            tag!("f")
-        )               >>
-        (AnsiSequence::CursorPos(x, y))
-    )
-);
+fn parse_def_cursor_int(input: &str) -> IResult<&str, u32> {
+    map(digit0, |s: &str| s.parse::<u32>().unwrap_or(1))(input)
+}
 
-named!(
-    escape<&str, AnsiSequence>,
-    do_parse!(
-        tag!("\u{1b}") >>
-        (AnsiSequence::Escape)
-    )
-);
+fn cursor_pos(input: &str) -> IResult<&str, AnsiSequence> {
+    map(
+        tuple((
+            tag("["),
+            parse_def_cursor_int,
+            opt(tag(";")),
+            parse_def_cursor_int,
+            alt((tag("H"), tag("f"))),
+        )),
+        |(_, x, _, y, _)| AnsiSequence::CursorPos(x, y),
+    )(input)
+}
 
-named!(
-    cursor_up<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")                >>
-        am: parse_def_cursor_int >>
-        tag!("A")                >>
-        (AnsiSequence::CursorUp(am))
-    )
-);
+fn escape(input: &str) -> IResult<&str, AnsiSequence> {
+    value(AnsiSequence::Escape, tag("\u{1b}"))(input)
+}
 
-named!(
-    cursor_down<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")                >>
-        am: parse_def_cursor_int >>
-        tag!("B")                >>
-        (AnsiSequence::CursorDown(am))
-    )
-);
+fn cursor_up(input: &str) -> IResult<&str, AnsiSequence> {
+    map(delimited(tag("["), parse_def_cursor_int, tag("A")), |am| {
+        AnsiSequence::CursorUp(am)
+    })(input)
+}
 
-named!(
-    cursor_forward<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")                >>
-        am: parse_def_cursor_int >>
-        tag!("C")                >>
-        (AnsiSequence::CursorForward(am))
-    )
-);
+fn cursor_down(input: &str) -> IResult<&str, AnsiSequence> {
+    map(delimited(tag("["), parse_def_cursor_int, tag("B")), |am| {
+        AnsiSequence::CursorDown(am)
+    })(input)
+}
 
-named!(
-    cursor_backward<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")                >>
-        am: parse_def_cursor_int >>
-        tag!("D")                >>
-        (AnsiSequence::CursorBackward(am))
-    )
-);
+fn cursor_forward(input: &str) -> IResult<&str, AnsiSequence> {
+    map(delimited(tag("["), parse_def_cursor_int, tag("C")), |am| {
+        AnsiSequence::CursorForward(am)
+    })(input)
+}
 
-named!(
-    graphics_mode1<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")       >>
-        val: parse_int >>
-        tag!("m")      >>
-        val: expr_res!(val.try_into()) >>
-        conv: expr_res!(Vec::from_slice(&[val])) >>
-        (AnsiSequence::SetGraphicsMode(conv))
-    )
-);
+fn cursor_backward(input: &str) -> IResult<&str, AnsiSequence> {
+    map(delimited(tag("["), parse_def_cursor_int, tag("D")), |am| {
+        AnsiSequence::CursorBackward(am)
+    })(input)
+}
 
-named!(
-    graphics_mode2<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")       >>
-        val1: parse_int >>
-        tag!(";")       >>
-        val2: parse_int >>
-        tag!("m")       >>
-        val1: expr_res!(val1.try_into()) >>
-        val2: expr_res!(val2.try_into()) >>
-        conv: expr_res!(Vec::from_slice(&[
-            val1,
-            val2,
-        ])) >>
-        (AnsiSequence::SetGraphicsMode(conv))
-    )
-);
+fn graphics_mode1(input: &str) -> IResult<&str, AnsiSequence> {
+    map(delimited(tag("["), parse_u8, tag("m")), |val| {
+        let mode =
+            Vec::from_slice(&[val]).expect("Vec::from_slice should allocate sufficient size");
+        AnsiSequence::SetGraphicsMode(mode)
+    })(input)
+}
 
-named!(
-    graphics_mode3<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")       >>
-        val1: parse_int >>
-        tag!(";")       >>
-        val2: parse_int >>
-        tag!(";")       >>
-        val3: parse_int >>
-        tag!("m")       >>
-        val1: expr_res!(val1.try_into()) >>
-        val2: expr_res!(val2.try_into()) >>
-        val3: expr_res!(val3.try_into()) >>
-        conv: expr_res!(Vec::from_slice(&[
-            val1,
-            val2,
-            val3,
-        ])) >>
-        (AnsiSequence::SetGraphicsMode(conv))
-    )
-);
+fn graphics_mode2(input: &str) -> IResult<&str, AnsiSequence> {
+    map(
+        tuple((tag("["), parse_u8, tag(";"), parse_u8, tag("m"))),
+        |(_, val1, _, val2, _)| {
+            let mode = Vec::from_slice(&[val1, val2])
+                .expect("Vec::from_slice should allocate sufficient size");
+            AnsiSequence::SetGraphicsMode(mode)
+        },
+    )(input)
+}
 
-named!(
-    graphics_mode4<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[m") >>
-        (AnsiSequence::SetGraphicsMode(Vec::new()))
-    )
-);
+fn graphics_mode3(input: &str) -> IResult<&str, AnsiSequence> {
+    map(
+        tuple((
+            tag("["),
+            parse_u8,
+            tag(";"),
+            parse_u8,
+            tag(";"),
+            parse_u8,
+            tag("m"),
+        )),
+        |(_, val1, _, val2, _, val3, _)| {
+            let mode = Vec::from_slice(&[val1, val2, val3])
+                .expect("Vec::from_slice should allocate sufficient size");
+            AnsiSequence::SetGraphicsMode(mode)
+        },
+    )(input)
+}
 
-named!(
-    graphics_mode5<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")       >>
-        val1: parse_int >>
-        tag!(";")       >>
-        val2: parse_int >>
-        tag!(";")       >>
-        val3: parse_int >>
-        tag!(";")       >>
-        val4: parse_int >>
-        tag!(";")       >>
-        val5: parse_int >>
-        tag!("m")       >>
-        val1: expr_res!(val1.try_into()) >>
-        val2: expr_res!(val2.try_into()) >>
-        val3: expr_res!(val3.try_into()) >>
-        val4: expr_res!(val4.try_into()) >>
-        val5: expr_res!(val5.try_into()) >>
-        conv: expr_res!(Vec::from_slice(&[
-            val1,
-            val2,
-            val3,
-            val4,
-            val5,
-        ])) >>
-        (AnsiSequence::SetGraphicsMode(conv))
-    )
-);
+fn graphics_mode4(input: &str) -> IResult<&str, AnsiSequence> {
+    value(AnsiSequence::SetGraphicsMode(Vec::new()), tag("[m"))(input)
+}
 
+fn graphics_mode5(input: &str) -> IResult<&str, AnsiSequence> {
+    map(
+        tuple((
+            tag("["),
+            parse_u8,
+            tag(";"),
+            parse_u8,
+            tag(";"),
+            parse_u8,
+            tag(";"),
+            parse_u8,
+            tag(";"),
+            parse_u8,
+            tag("m"),
+        )),
+        |(_, val1, _, val2, _, val3, _, val4, _, val5, _)| {
+            let mode = Vec::from_slice(&[val1, val2, val3, val4, val5])
+                .expect("Vec::from_slice should allocate sufficient size");
+            AnsiSequence::SetGraphicsMode(mode)
+        },
+    )(input)
+}
 
-named!(
-    graphics_mode<&str, AnsiSequence>,
-    alt!(
-          graphics_mode1
-        | graphics_mode2
-        | graphics_mode3
-        | graphics_mode4
-        | graphics_mode5
-    )
-);
+fn graphics_mode(input: &str) -> IResult<&str, AnsiSequence> {
+    alt((
+        graphics_mode1,
+        graphics_mode2,
+        graphics_mode3,
+        graphics_mode4,
+        graphics_mode5,
+    ))(input)
+}
 
-named!(
-    set_mode<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[=")                       >>
-        mode: parse_int                  >>
-        conv: expr_res!(mode.try_into()) >>
-        tag!("h")                        >>
-        (AnsiSequence::SetMode(conv))
-    )
-);
+fn set_mode(input: &str) -> IResult<&str, AnsiSequence> {
+    map(delimited(tag("[="), parse_u8, tag("h")), |val| {
+        AnsiSequence::SetMode(val)
+    })(input)
+}
 
-named!(
-    reset_mode<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[=")                       >>
-        mode: parse_int                  >>
-        conv: expr_res!(mode.try_into()) >>
-        tag!("l")                        >>
-        (AnsiSequence::ResetMode(conv))
-    )
-);
+fn reset_mode(input: &str) -> IResult<&str, AnsiSequence> {
+    map(delimited(tag("[="), parse_u8, tag("l")), |val| {
+        AnsiSequence::ResetMode(val)
+    })(input)
+}
 
-named!(
-    set_top_and_bottom<&str, AnsiSequence>,
-    do_parse!(
-        tag!("[")    >>
-        x: parse_int >>
-        tag!(";")    >>
-        y: parse_int >>
-        tag!("r")    >>
-        (AnsiSequence::SetTopAndBottom(x, y))
-    )
-);
+fn set_top_and_bottom(input: &str) -> IResult<&str, AnsiSequence> {
+    map(
+        tuple((tag("["), parse_u32, tag(";"), parse_u32, tag("r"))),
+        |(_, x, _, y, _)| AnsiSequence::SetTopAndBottom(x, y),
+    )(input)
+}
 
-tag_parser!(cursor_save,           "[s", AnsiSequence::CursorSave);
-tag_parser!(cursor_restore,        "[u", AnsiSequence::CursorRestore);
-tag_parser!(erase_display,        "[2J", AnsiSequence::EraseDisplay);
-tag_parser!(erase_line,            "[K", AnsiSequence::EraseLine);
-tag_parser!(hide_cursor,        "[?25l", AnsiSequence::HideCursor);
-tag_parser!(show_cursor,        "[?25h", AnsiSequence::ShowCursor);
-tag_parser!(cursor_to_app,       "[?1h", AnsiSequence::CursorToApp);
-tag_parser!(set_new_line_mode,   "[20h", AnsiSequence::SetNewLineMode);
-tag_parser!(set_col_132,         "[?3h", AnsiSequence::SetCol132);
-tag_parser!(set_smooth_scroll,   "[?4h", AnsiSequence::SetSmoothScroll);
-tag_parser!(set_reverse_video,   "[?5h", AnsiSequence::SetReverseVideo);
-tag_parser!(set_origin_rel,      "[?6h", AnsiSequence::SetOriginRelative);
-tag_parser!(set_auto_wrap,       "[?7h", AnsiSequence::SetAutoWrap);
-tag_parser!(set_auto_repeat,     "[?8h", AnsiSequence::SetAutoRepeat);
-tag_parser!(set_interlacing,     "[?9h", AnsiSequence::SetInterlacing);
-tag_parser!(set_linefeed,        "[20l", AnsiSequence::SetLineFeedMode);
-tag_parser!(set_cursorkey,       "[?1l", AnsiSequence::SetCursorKeyToCursor);
-tag_parser!(set_vt52,            "[?2l", AnsiSequence::SetVT52);
-tag_parser!(set_col80,           "[?3l", AnsiSequence::SetCol80);
-tag_parser!(set_jump_scroll,     "[?4l", AnsiSequence::SetJumpScrolling);
-tag_parser!(set_normal_video,    "[?5l", AnsiSequence::SetNormalVideo);
-tag_parser!(set_origin_abs,      "[?6l", AnsiSequence::SetOriginAbsolute);
-tag_parser!(reset_auto_wrap,     "[?7l", AnsiSequence::ResetAutoWrap);
-tag_parser!(reset_auto_repeat,   "[?8l", AnsiSequence::ResetAutoRepeat);
-tag_parser!(reset_interlacing,   "[?9l", AnsiSequence::ResetInterlacing);
+tag_parser!(cursor_save, "[s", AnsiSequence::CursorSave);
+tag_parser!(cursor_restore, "[u", AnsiSequence::CursorRestore);
+tag_parser!(erase_display, "[2J", AnsiSequence::EraseDisplay);
+tag_parser!(erase_line, "[K", AnsiSequence::EraseLine);
+tag_parser!(hide_cursor, "[?25l", AnsiSequence::HideCursor);
+tag_parser!(show_cursor, "[?25h", AnsiSequence::ShowCursor);
+tag_parser!(cursor_to_app, "[?1h", AnsiSequence::CursorToApp);
+tag_parser!(set_new_line_mode, "[20h", AnsiSequence::SetNewLineMode);
+tag_parser!(set_col_132, "[?3h", AnsiSequence::SetCol132);
+tag_parser!(set_smooth_scroll, "[?4h", AnsiSequence::SetSmoothScroll);
+tag_parser!(set_reverse_video, "[?5h", AnsiSequence::SetReverseVideo);
+tag_parser!(set_origin_rel, "[?6h", AnsiSequence::SetOriginRelative);
+tag_parser!(set_auto_wrap, "[?7h", AnsiSequence::SetAutoWrap);
+tag_parser!(set_auto_repeat, "[?8h", AnsiSequence::SetAutoRepeat);
+tag_parser!(set_interlacing, "[?9h", AnsiSequence::SetInterlacing);
+tag_parser!(set_linefeed, "[20l", AnsiSequence::SetLineFeedMode);
+tag_parser!(set_cursorkey, "[?1l", AnsiSequence::SetCursorKeyToCursor);
+tag_parser!(set_vt52, "[?2l", AnsiSequence::SetVT52);
+tag_parser!(set_col80, "[?3l", AnsiSequence::SetCol80);
+tag_parser!(set_jump_scroll, "[?4l", AnsiSequence::SetJumpScrolling);
+tag_parser!(set_normal_video, "[?5l", AnsiSequence::SetNormalVideo);
+tag_parser!(set_origin_abs, "[?6l", AnsiSequence::SetOriginAbsolute);
+tag_parser!(reset_auto_wrap, "[?7l", AnsiSequence::ResetAutoWrap);
+tag_parser!(reset_auto_repeat, "[?8l", AnsiSequence::ResetAutoRepeat);
+tag_parser!(reset_interlacing, "[?9l", AnsiSequence::ResetInterlacing);
 
 tag_parser!(set_alternate_keypad, "=", AnsiSequence::SetAlternateKeypad);
 tag_parser!(set_numeric_keypad, ">", AnsiSequence::SetNumericKeypad);
@@ -268,8 +200,8 @@ tag_parser!(set_uk_g0, "(A", AnsiSequence::SetUKG0);
 tag_parser!(set_uk_g1, ")A", AnsiSequence::SetUKG1);
 tag_parser!(set_us_g0, "(B", AnsiSequence::SetUSG0);
 tag_parser!(set_us_g1, ")B", AnsiSequence::SetUSG1);
-tag_parser!(set_g0_special,   "(0", AnsiSequence::SetG0SpecialChars);
-tag_parser!(set_g1_special,   ")0", AnsiSequence::SetG1SpecialChars);
+tag_parser!(set_g0_special, "(0", AnsiSequence::SetG0SpecialChars);
+tag_parser!(set_g1_special, ")0", AnsiSequence::SetG1SpecialChars);
 tag_parser!(set_g0_alternate, "(1", AnsiSequence::SetG0AlternateChar);
 tag_parser!(set_g1_alternate, ")1", AnsiSequence::SetG1AlternateChar);
 tag_parser!(set_g0_graph, "(2", AnsiSequence::SetG0AltAndSpecialGraph);
@@ -277,66 +209,67 @@ tag_parser!(set_g1_graph, ")2", AnsiSequence::SetG1AltAndSpecialGraph);
 tag_parser!(set_single_shift2, "N", AnsiSequence::SetSingleShift2);
 tag_parser!(set_single_shift3, "O", AnsiSequence::SetSingleShift3);
 
-named!(
-    combined<&str, AnsiSequence>,
-    alt!(
-          escape
-        | cursor_pos
-        | cursor_up
-        | cursor_down
-        | cursor_forward
-        | cursor_backward
-        | cursor_save
-        | cursor_restore
-        | erase_display
-        | erase_line
-        | graphics_mode
-        | set_mode
-        | reset_mode
-        | hide_cursor
-        | show_cursor
-        | cursor_to_app
-        | set_new_line_mode
-        | set_col_132
-        | set_smooth_scroll
-        | set_reverse_video
-        | set_origin_rel
-        | set_auto_wrap
-        | set_auto_repeat
-        | set_interlacing
-        | set_linefeed
-        | set_cursorkey
-        | set_vt52
-        | set_col80
-        | set_jump_scroll
-        | set_normal_video
-        | set_origin_abs
-        | reset_auto_wrap
-        | reset_auto_repeat
-        | reset_interlacing
-        | set_top_and_bottom
-        | set_alternate_keypad
-        | set_numeric_keypad
-        | set_uk_g0
-        | set_uk_g1
-        | set_us_g0
-        | set_us_g1
-        | set_g0_special
-        | set_g1_special
-        | set_g0_alternate
-        | set_g1_alternate
-        | set_g0_graph
-        | set_g1_graph
-        | set_single_shift2
-        | set_single_shift3
-    )
-);
+fn combined(input: &str) -> IResult<&str, AnsiSequence> {
+    // `alt` only supports up to 21 parsers, and nom doesn't seem to
+    // have an alternative with higher variability.
+    // So we simply nest them.
+    alt((
+        alt((
+            escape,
+            cursor_pos,
+            cursor_up,
+            cursor_down,
+            cursor_forward,
+            cursor_backward,
+            cursor_save,
+            cursor_restore,
+            erase_display,
+            erase_line,
+            graphics_mode,
+            set_mode,
+            reset_mode,
+            hide_cursor,
+            show_cursor,
+            cursor_to_app,
+            set_new_line_mode,
+            set_col_132,
+            set_smooth_scroll,
+            set_reverse_video,
+            set_origin_rel,
+        )),
+        alt((
+            set_auto_wrap,
+            set_auto_repeat,
+            set_interlacing,
+            set_linefeed,
+            set_cursorkey,
+            set_vt52,
+            set_col80,
+            set_jump_scroll,
+            set_normal_video,
+            set_origin_abs,
+            reset_auto_wrap,
+            reset_auto_repeat,
+            reset_interlacing,
+            set_top_and_bottom,
+            set_alternate_keypad,
+            set_numeric_keypad,
+            set_uk_g0,
+            set_uk_g1,
+            set_us_g0,
+            set_us_g1,
+            set_g0_special,
+        )),
+        set_g1_special,
+        set_g0_alternate,
+        set_g1_alternate,
+        set_g0_graph,
+        set_g1_graph,
+        set_single_shift2,
+        set_single_shift3,
+    ))(input)
+}
 
-named!(
-    pub parse_escape<&str, AnsiSequence>,
-    do_parse!(
-        tag!("\u{1b}")    >>
-        seq: combined     >>
-        (seq)
-    )
-);
+pub fn parse_escape(input: &str) -> IResult<&str, AnsiSequence> {
+    preceded(tag("\u{1b}"), combined)(input)
+}
