1use crate::{util::ws, KconfigInput};
2use nom::{
3 branch::alt,
4 bytes::complete::tag,
5 character::complete::{alphanumeric1, one_of},
6 combinator::{map, recognize},
7 error::{Error, ErrorKind, ParseError},
8 multi::many1,
9 sequence::delimited,
10 IResult, Input, Parser,
11};
12
13pub fn parse_string(input: KconfigInput) -> IResult<KconfigInput, String> {
14 map(
15 alt((
16 delimited(tag("'"), take_until_unbalanced('\''), tag("'")),
17 delimited(tag("\""), take_until_unbalanced('"'), tag("\"")),
18 )),
19 |d| d.fragment().to_string(),
20 )
21 .parse(input)
22}
23
24pub fn take_until_unbalanced(
25 delimiter: char,
26) -> impl Fn(KconfigInput) -> IResult<KconfigInput, KconfigInput> {
27 move |i: KconfigInput| {
28 let mut index: usize = 0;
29 let mut delimiter_counter = 0;
30
31 let end_of_line = match &i.find('\n') {
32 Some(e) => *e,
33 None => i.len(),
34 };
35
36 while let Some(n) = &i[index..end_of_line].find(delimiter) {
37 delimiter_counter += 1;
38 index += n + 1;
39 }
40
41 match index.checked_sub(1) {
43 Some(i) => index = i,
44 None => {
45 return Err(nom::Err::Error(Error::from_error_kind(
46 i,
47 ErrorKind::TakeUntil,
48 )))
49 }
50 }
51 delimiter_counter -= 1;
53
54 match delimiter_counter % 2 == 0 {
55 true => Ok(i.take_split(index)),
56 false => Err(nom::Err::Error(Error::from_error_kind(
57 i,
58 ErrorKind::TakeUntil,
59 ))),
60 }
61 }
62}
63
64pub fn parse_first_word(input: KconfigInput) -> IResult<KconfigInput, KconfigInput> {
67 alt((
68 recognize((tag("'"), take_until_first_word_end('\''), tag("'"))),
69 recognize((tag("\""), take_until_first_word_end('"'), tag("\""))),
70 recognize(ws(many1(alt((alphanumeric1, recognize(one_of("-._'\""))))))),
71 ))
72 .parse(input)
73}
74
75fn take_until_first_word_end(
76 delimiter: char,
77) -> impl Fn(KconfigInput) -> IResult<KconfigInput, KconfigInput> {
78 move |i: KconfigInput| {
79 let input = *i.fragment();
80 let end_of_line = input.find('\n').unwrap_or(input.len());
81 let search_start = 0;
82
83 if let Some(offset) = input[search_start..end_of_line].find(delimiter) {
84 let index = search_start + offset;
85 return Ok(i.take_split(index));
86 }
87
88 Err(nom::Err::Error(Error::from_error_kind(
89 i,
90 ErrorKind::TakeUntil,
91 )))
92 }
93}