1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::ops::{Range, RangeFrom, RangeTo};

use nom::{
    branch::alt,
    bytes::complete::tag,
    character::complete::{line_ending, multispace1, not_line_ending, space1},
    combinator::{eof, value},
    error::ParseError,
    multi::many0,
    sequence::{preceded, terminated},
    AsChar, Compare, IResult, InputIter, InputLength, InputTake, InputTakeAtPosition, Slice,
};

use crate::KconfigInput;

/// ignores comments
///
/// # Example
/// ```
/// use nom::combinator::eof;
/// use nom::bytes::complete::tag;
/// use nom_kconfig::util::ws_comment;
/// let input = r#"# a comment#   \
///
/// hello"#;
/// assert_eq!(ws_comment::<&str, ()>(input), Ok(("hello", ())))
/// ```
pub fn ws_comment<I, E: ParseError<I>>(input: I) -> IResult<I, (), E>
where
    I: Clone + InputLength + InputTake,
    I: InputTakeAtPosition,
    <I as InputTakeAtPosition>::Item: AsChar + Clone,
    <I as InputIter>::Item: Clone,
    I: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
    I: InputIter + InputLength,
    I: Compare<&'static str>,
    <I as InputIter>::Item: AsChar,
    <I as InputIter>::Item: AsChar,
{
    value(
        (),
        many0(alt((
            // TODO 3.0.19/drivers/staging/iio/light/Kconfig, backslash??
            preceded(
                alt((tag("#"), tag("\\#"))),
                terminated(not_line_ending, alt((line_ending, eof))),
            ),
            multispace1,
            // TODO linux v3.2, in file /drivers/dma/Kconfig
            tag(" "),
        ))),
    )(input)
}
/// Gets rid of comments, spaces, tabs and newlines.
///
/// # Example
/// ```
/// use nom::bytes::complete::tag;
/// use nom_kconfig::util::ws;
/// let input = r#"# a comment#   \
///
/// hello"#;
/// assert_eq!(ws(tag::<&str, &str, ()>("hello"))(input), Ok(("", "hello")))
/// ```
pub fn ws<I, F, O, E: ParseError<I>>(inner: F) -> impl FnMut(I) -> IResult<I, O, E>
where
    I: Clone + InputLength + InputTake,
    <I as InputIter>::Item: Clone,
    I: InputTakeAtPosition,
    <I as InputTakeAtPosition>::Item: AsChar + Clone,
    I: InputTakeAtPosition,
    <I as InputTakeAtPosition>::Item: AsChar,
    I: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
    I: InputIter + InputLength,
    I: Compare<&'static str>,
    <I as InputIter>::Item: AsChar,
    <I as InputIter>::Item: AsChar,
    F: FnMut(I) -> IResult<I, O, E>,
{
    preceded(ws_comment, inner)
}

/// Parses the content until EOF or new line.
///
/// # Example
/// ```rust
/// use nom::combinator::map;
/// use nom_kconfig::util::parse_until_eol;
/// use nom_kconfig::KconfigInput;
///
/// let input  = KconfigInput::new_extra("parse me if you\ncan!", Default::default());
/// let (remaining, line) = parse_until_eol(input).unwrap();
/// assert_eq!(line.to_string(), "parse me if you");
/// assert_eq!(remaining.to_string(), "can!");
/// ```
///
pub fn parse_until_eol(input: KconfigInput) -> IResult<KconfigInput, KconfigInput> {
    terminated(not_line_ending, alt((line_ending, eof)))(input)
}

/// Gets rid of spaces, tabs and backslash + newline.
/// # Example
/// ```
/// use nom::bytes::complete::tag;
/// use nom_kconfig::util::wsi;
/// let input = r#"   \
/// hello"#;
/// assert_eq!(wsi(tag::<&str, &str, ()>("hello"))(input), Ok(("", "hello")))
/// ```
pub fn wsi<I, F, O, E: ParseError<I>>(inner: F) -> impl FnMut(I) -> IResult<I, O, E>
where
    I: Clone + InputLength + InputTake,
    <I as InputIter>::Item: Clone,
    I: InputTakeAtPosition,
    <I as InputTakeAtPosition>::Item: AsChar + Clone,
    I: InputTakeAtPosition,
    <I as InputTakeAtPosition>::Item: AsChar,
    I: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
    I: InputIter + InputLength,
    I: Compare<&'static str>,
    <I as InputIter>::Item: AsChar,
    <I as InputIter>::Item: AsChar,
    F: FnMut(I) -> IResult<I, O, E>,
{
    preceded(
        value((), many0(alt((preceded(tag("\\"), line_ending), space1)))),
        inner,
    )
}