Merge branch 'issue/outdated-nom' into 'master'

Update to nom@7

See merge request davidbittner/ansi-parser!13
This commit is contained in:
David Bittner
2024-01-16 18:57:53 +00:00
2 changed files with 204 additions and 270 deletions

View File

@@ -14,7 +14,7 @@ heapless = "0.6.1"
[dependencies.nom] [dependencies.nom]
default-features = false default-features = false
version = "4.2.3" version = "7.1.3"
[features] [features]
default = ["std"] default = ["std"]

View File

@@ -3,237 +3,170 @@ mod tests;
use crate::AnsiSequence; use crate::AnsiSequence;
use core::convert::TryInto;
use heapless::Vec; 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 { macro_rules! tag_parser {
($sig:ident, $tag:expr, $ret:expr) => { ($sig:ident, $tag:expr, $ret:expr) => {
named!( fn $sig(input: &str) -> IResult<&str, AnsiSequence> {
$sig<&str, AnsiSequence>, value($ret, tag($tag))(input)
do_parse!( }
tag!($tag) >> };
($ret)
)
);
}
} }
named!( fn parse_u32(input: &str) -> IResult<&str, u32> {
parse_int<&str, u32>, map_res(digit1, |s: &str| s.parse::<u32>())(input)
map_res!( }
nom::digit,
|s: &str| s.parse::<u32>() 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 // 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). // all escapes with defaults (not just those that default to 1).
named!( fn parse_def_cursor_int(input: &str) -> IResult<&str, u32> {
parse_def_cursor_int<&str, u32>, map(digit0, |s: &str| s.parse::<u32>().unwrap_or(1))(input)
map!( }
nom::digit0,
|s: &str| s.parse::<u32>().unwrap_or(1)
)
);
named!( fn cursor_pos(input: &str) -> IResult<&str, AnsiSequence> {
cursor_pos<&str, AnsiSequence>, map(
do_parse!( tuple((
tag!("[") >> tag("["),
x: parse_def_cursor_int >> parse_def_cursor_int,
opt!(tag!(";")) >> opt(tag(";")),
y: parse_def_cursor_int >> parse_def_cursor_int,
alt!( alt((tag("H"), tag("f"))),
tag!("H") | )),
tag!("f") |(_, x, _, y, _)| AnsiSequence::CursorPos(x, y),
) >> )(input)
(AnsiSequence::CursorPos(x, y)) }
)
);
named!( fn escape(input: &str) -> IResult<&str, AnsiSequence> {
escape<&str, AnsiSequence>, value(AnsiSequence::Escape, tag("\u{1b}"))(input)
do_parse!( }
tag!("\u{1b}") >>
(AnsiSequence::Escape)
)
);
named!( fn cursor_up(input: &str) -> IResult<&str, AnsiSequence> {
cursor_up<&str, AnsiSequence>, map(delimited(tag("["), parse_def_cursor_int, tag("A")), |am| {
do_parse!( AnsiSequence::CursorUp(am)
tag!("[") >> })(input)
am: parse_def_cursor_int >> }
tag!("A") >>
(AnsiSequence::CursorUp(am))
)
);
named!( fn cursor_down(input: &str) -> IResult<&str, AnsiSequence> {
cursor_down<&str, AnsiSequence>, map(delimited(tag("["), parse_def_cursor_int, tag("B")), |am| {
do_parse!( AnsiSequence::CursorDown(am)
tag!("[") >> })(input)
am: parse_def_cursor_int >> }
tag!("B") >>
(AnsiSequence::CursorDown(am))
)
);
named!( fn cursor_forward(input: &str) -> IResult<&str, AnsiSequence> {
cursor_forward<&str, AnsiSequence>, map(delimited(tag("["), parse_def_cursor_int, tag("C")), |am| {
do_parse!( AnsiSequence::CursorForward(am)
tag!("[") >> })(input)
am: parse_def_cursor_int >> }
tag!("C") >>
(AnsiSequence::CursorForward(am))
)
);
named!( fn cursor_backward(input: &str) -> IResult<&str, AnsiSequence> {
cursor_backward<&str, AnsiSequence>, map(delimited(tag("["), parse_def_cursor_int, tag("D")), |am| {
do_parse!( AnsiSequence::CursorBackward(am)
tag!("[") >> })(input)
am: parse_def_cursor_int >> }
tag!("D") >>
(AnsiSequence::CursorBackward(am))
)
);
named!( fn graphics_mode1(input: &str) -> IResult<&str, AnsiSequence> {
graphics_mode1<&str, AnsiSequence>, map(delimited(tag("["), parse_u8, tag("m")), |val| {
do_parse!( let mode =
tag!("[") >> Vec::from_slice(&[val]).expect("Vec::from_slice should allocate sufficient size");
val: parse_int >> AnsiSequence::SetGraphicsMode(mode)
tag!("m") >> })(input)
val: expr_res!(val.try_into()) >> }
conv: expr_res!(Vec::from_slice(&[val])) >>
(AnsiSequence::SetGraphicsMode(conv))
)
);
named!( fn graphics_mode2(input: &str) -> IResult<&str, AnsiSequence> {
graphics_mode2<&str, AnsiSequence>, map(
do_parse!( tuple((tag("["), parse_u8, tag(";"), parse_u8, tag("m"))),
tag!("[") >> |(_, val1, _, val2, _)| {
val1: parse_int >> let mode = Vec::from_slice(&[val1, val2])
tag!(";") >> .expect("Vec::from_slice should allocate sufficient size");
val2: parse_int >> AnsiSequence::SetGraphicsMode(mode)
tag!("m") >> },
val1: expr_res!(val1.try_into()) >> )(input)
val2: expr_res!(val2.try_into()) >> }
conv: expr_res!(Vec::from_slice(&[
val1,
val2,
])) >>
(AnsiSequence::SetGraphicsMode(conv))
)
);
named!( fn graphics_mode3(input: &str) -> IResult<&str, AnsiSequence> {
graphics_mode3<&str, AnsiSequence>, map(
do_parse!( tuple((
tag!("[") >> tag("["),
val1: parse_int >> parse_u8,
tag!(";") >> tag(";"),
val2: parse_int >> parse_u8,
tag!(";") >> tag(";"),
val3: parse_int >> parse_u8,
tag!("m") >> tag("m"),
val1: expr_res!(val1.try_into()) >> )),
val2: expr_res!(val2.try_into()) >> |(_, val1, _, val2, _, val3, _)| {
val3: expr_res!(val3.try_into()) >> let mode = Vec::from_slice(&[val1, val2, val3])
conv: expr_res!(Vec::from_slice(&[ .expect("Vec::from_slice should allocate sufficient size");
val1, AnsiSequence::SetGraphicsMode(mode)
val2, },
val3, )(input)
])) >> }
(AnsiSequence::SetGraphicsMode(conv))
)
);
named!( fn graphics_mode4(input: &str) -> IResult<&str, AnsiSequence> {
graphics_mode4<&str, AnsiSequence>, value(AnsiSequence::SetGraphicsMode(Vec::new()), tag("[m"))(input)
do_parse!( }
tag!("[m") >>
(AnsiSequence::SetGraphicsMode(Vec::new()))
)
);
named!( fn graphics_mode5(input: &str) -> IResult<&str, AnsiSequence> {
graphics_mode5<&str, AnsiSequence>, map(
do_parse!( tuple((
tag!("[") >> tag("["),
val1: parse_int >> parse_u8,
tag!(";") >> tag(";"),
val2: parse_int >> parse_u8,
tag!(";") >> tag(";"),
val3: parse_int >> parse_u8,
tag!(";") >> tag(";"),
val4: parse_int >> parse_u8,
tag!(";") >> tag(";"),
val5: parse_int >> parse_u8,
tag!("m") >> tag("m"),
val1: expr_res!(val1.try_into()) >> )),
val2: expr_res!(val2.try_into()) >> |(_, val1, _, val2, _, val3, _, val4, _, val5, _)| {
val3: expr_res!(val3.try_into()) >> let mode = Vec::from_slice(&[val1, val2, val3, val4, val5])
val4: expr_res!(val4.try_into()) >> .expect("Vec::from_slice should allocate sufficient size");
val5: expr_res!(val5.try_into()) >> AnsiSequence::SetGraphicsMode(mode)
conv: expr_res!(Vec::from_slice(&[ },
val1, )(input)
val2, }
val3,
val4,
val5,
])) >>
(AnsiSequence::SetGraphicsMode(conv))
)
);
named!( fn graphics_mode(input: &str) -> IResult<&str, AnsiSequence> {
graphics_mode<&str, AnsiSequence>, alt((
alt!( graphics_mode1,
graphics_mode1 graphics_mode2,
| graphics_mode2 graphics_mode3,
| graphics_mode3 graphics_mode4,
| graphics_mode4 graphics_mode5,
| graphics_mode5 ))(input)
) }
);
named!( fn set_mode(input: &str) -> IResult<&str, AnsiSequence> {
set_mode<&str, AnsiSequence>, map(delimited(tag("[="), parse_u8, tag("h")), |val| {
do_parse!( AnsiSequence::SetMode(val)
tag!("[=") >> })(input)
mode: parse_int >> }
conv: expr_res!(mode.try_into()) >>
tag!("h") >>
(AnsiSequence::SetMode(conv))
)
);
named!( fn reset_mode(input: &str) -> IResult<&str, AnsiSequence> {
reset_mode<&str, AnsiSequence>, map(delimited(tag("[="), parse_u8, tag("l")), |val| {
do_parse!( AnsiSequence::ResetMode(val)
tag!("[=") >> })(input)
mode: parse_int >> }
conv: expr_res!(mode.try_into()) >>
tag!("l") >>
(AnsiSequence::ResetMode(conv))
)
);
named!( fn set_top_and_bottom(input: &str) -> IResult<&str, AnsiSequence> {
set_top_and_bottom<&str, AnsiSequence>, map(
do_parse!( tuple((tag("["), parse_u32, tag(";"), parse_u32, tag("r"))),
tag!("[") >> |(_, x, _, y, _)| AnsiSequence::SetTopAndBottom(x, y),
x: parse_int >> )(input)
tag!(";") >> }
y: parse_int >>
tag!("r") >>
(AnsiSequence::SetTopAndBottom(x, y))
)
);
tag_parser!(cursor_save, "[s", AnsiSequence::CursorSave); tag_parser!(cursor_save, "[s", AnsiSequence::CursorSave);
tag_parser!(cursor_restore, "[u", AnsiSequence::CursorRestore); tag_parser!(cursor_restore, "[u", AnsiSequence::CursorRestore);
@@ -276,66 +209,67 @@ tag_parser!(set_g1_graph, ")2", AnsiSequence::SetG1AltAndSpecialGraph);
tag_parser!(set_single_shift2, "N", AnsiSequence::SetSingleShift2); tag_parser!(set_single_shift2, "N", AnsiSequence::SetSingleShift2);
tag_parser!(set_single_shift3, "O", AnsiSequence::SetSingleShift3); tag_parser!(set_single_shift3, "O", AnsiSequence::SetSingleShift3);
named!( fn combined(input: &str) -> IResult<&str, AnsiSequence> {
combined<&str, AnsiSequence>, // `alt` only supports up to 21 parsers, and nom doesn't seem to
alt!( // have an alternative with higher variability.
escape // So we simply nest them.
| cursor_pos alt((
| cursor_up alt((
| cursor_down escape,
| cursor_forward cursor_pos,
| cursor_backward cursor_up,
| cursor_save cursor_down,
| cursor_restore cursor_forward,
| erase_display cursor_backward,
| erase_line cursor_save,
| graphics_mode cursor_restore,
| set_mode erase_display,
| reset_mode erase_line,
| hide_cursor graphics_mode,
| show_cursor set_mode,
| cursor_to_app reset_mode,
| set_new_line_mode hide_cursor,
| set_col_132 show_cursor,
| set_smooth_scroll cursor_to_app,
| set_reverse_video set_new_line_mode,
| set_origin_rel set_col_132,
| set_auto_wrap set_smooth_scroll,
| set_auto_repeat set_reverse_video,
| set_interlacing set_origin_rel,
| set_linefeed )),
| set_cursorkey alt((
| set_vt52 set_auto_wrap,
| set_col80 set_auto_repeat,
| set_jump_scroll set_interlacing,
| set_normal_video set_linefeed,
| set_origin_abs set_cursorkey,
| reset_auto_wrap set_vt52,
| reset_auto_repeat set_col80,
| reset_interlacing set_jump_scroll,
| set_top_and_bottom set_normal_video,
| set_alternate_keypad set_origin_abs,
| set_numeric_keypad reset_auto_wrap,
| set_uk_g0 reset_auto_repeat,
| set_uk_g1 reset_interlacing,
| set_us_g0 set_top_and_bottom,
| set_us_g1 set_alternate_keypad,
| set_g0_special set_numeric_keypad,
| set_g1_special set_uk_g0,
| set_g0_alternate set_uk_g1,
| set_g1_alternate set_us_g0,
| set_g0_graph set_us_g1,
| set_g1_graph set_g0_special,
| set_single_shift2 )),
| set_single_shift3 set_g1_special,
) set_g0_alternate,
); set_g1_alternate,
set_g0_graph,
set_g1_graph,
set_single_shift2,
set_single_shift3,
))(input)
}
named!( pub fn parse_escape(input: &str) -> IResult<&str, AnsiSequence> {
pub parse_escape<&str, AnsiSequence>, preceded(tag("\u{1b}"), combined)(input)
do_parse!( }
tag!("\u{1b}") >>
seq: combined >>
(seq)
)
);