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