nom_kconfig/
util.rs

1use nom::{
2    branch::alt,
3    bytes::complete::tag,
4    character::complete::{line_ending, multispace1, not_line_ending, space1},
5    combinator::{eof, value},
6    error::ParseError,
7    multi::many0,
8    sequence::{preceded, terminated},
9    AsChar, Compare, IResult, Input, Parser,
10};
11
12use crate::KconfigInput;
13
14/// ignores comments
15///
16/// # Example
17/// ```
18/// use nom::combinator::eof;
19/// use nom::bytes::complete::tag;
20/// use nom_kconfig::util::ws_comment;
21/// let input = r#"# a comment#   \
22///
23/// hello"#;
24/// assert_eq!(ws_comment::<&str, ()>(input), Ok(("hello", ())))
25/// ```
26pub fn ws_comment<I, E: ParseError<I>>(input: I) -> IResult<I, (), E>
27where
28    I: Clone + Input,
29    I: Compare<&'static str>,
30    <I as Input>::Item: AsChar,
31{
32    value(
33        (),
34        many0(alt((
35            // TODO 3.0.19/drivers/staging/iio/light/Kconfig, backslash??
36            preceded(
37                alt((tag("#"), tag("\\#"))),
38                terminated(not_line_ending, alt((line_ending, eof))),
39            ),
40            multispace1,
41            // TODO linux v3.2, in file /drivers/dma/Kconfig
42            tag(" "),
43        ))),
44    )
45    .parse(input)
46}
47/// Gets rid of comments, spaces, tabs and newlines.
48///
49/// # Example
50/// ```
51/// use nom::bytes::complete::tag;
52/// use nom::Parser;
53/// use nom_kconfig::util::ws;
54/// let input = r#"# a comment#   \
55///
56/// hello"#;
57/// assert_eq!(ws(tag::<&str, &str, ()>("hello")).parse(input), Ok(("", "hello")))
58/// ```
59pub fn ws<I, F, O, E: ParseError<I>>(inner: F) -> impl Parser<I, Output = O, Error = E>
60where
61    I: Clone + Input,
62    I: Compare<&'static str>,
63    <I as Input>::Item: AsChar,
64    F: Parser<I, Output = O, Error = E>,
65{
66    preceded(ws_comment, inner)
67}
68
69/// Parses the content until EOF or new line.
70///
71/// # Example
72/// ```rust
73/// use nom::combinator::map;
74/// use nom_kconfig::util::parse_until_eol;
75/// use nom_kconfig::KconfigInput;
76///
77/// let input  = KconfigInput::new_extra("parse me if you\ncan!", Default::default());
78/// let (remaining, line) = parse_until_eol(input).unwrap();
79/// assert_eq!(line.to_string(), "parse me if you");
80/// assert_eq!(remaining.to_string(), "can!");
81/// ```
82///
83pub fn parse_until_eol(input: KconfigInput) -> IResult<KconfigInput, KconfigInput> {
84    terminated(not_line_ending, alt((line_ending, eof))).parse(input)
85}
86
87/// Gets rid of spaces, tabs and backslash + newline.
88/// # Example
89/// ```
90/// use nom::bytes::complete::tag;
91/// use nom::Parser;
92/// use nom_kconfig::util::wsi;
93/// let input = r#"   \
94/// hello"#;
95/// assert_eq!(wsi(tag::<&str, &str, ()>("hello")).parse(input), Ok(("", "hello")))
96/// ```
97pub fn wsi<I, F, O, E: ParseError<I>>(inner: F) -> impl Parser<I, Output = O, Error = E>
98where
99    I: Clone + Input,
100    I: Compare<&'static str>,
101    <I as Input>::Item: AsChar,
102    F: Parser<I, Output = O, Error = E>,
103{
104    preceded(
105        value((), many0(alt((preceded(tag("\\"), line_ending), space1)))),
106        inner,
107    )
108}