nom_kconfig/entry/
source.rs1use std::path::PathBuf;
2
3use nom::{
4 branch::alt,
5 bytes::complete::tag,
6 character::complete::{alphanumeric1, one_of},
7 combinator::{cut, map, recognize},
8 error::{Error, ErrorKind, ParseError},
9 multi::many1,
10 sequence::delimited,
11 IResult,
12};
13use regex::Regex;
14
15use crate::{
16 kconfig::{parse_kconfig, Kconfig},
17 util::{ws, wsi},
18 KconfigFile, KconfigInput,
19};
20
21pub fn parse_filepath(input: KconfigInput) -> IResult<KconfigInput, &str> {
22 map(
23 recognize(ws(many1(alt((
24 alphanumeric1::<KconfigInput, _>,
25 recognize(one_of(".$()-_$/")),
26 ))))),
27 |d| d.fragment().to_owned(),
28 )(input)
29}
30
31pub fn parse_source(input: KconfigInput) -> IResult<KconfigInput, Source> {
32 let (input, _) = ws(tag("source"))(input)?;
33 let (input, file) = wsi(alt((
34 delimited(tag("\""), parse_filepath, tag("\"")),
35 parse_filepath,
36 )))(input)?;
37 let source_kconfig_file = KconfigFile::new(input.clone().extra.root_dir, PathBuf::from(file));
38 if is_dynamic_source(file) {
39 return Ok((
40 input,
41 Source {
42 file: file.to_string(),
43 ..Default::default()
44 },
45 ));
46 }
47 let source_content = source_kconfig_file
48 .read_to_string()
49 .map_err(|_| nom::Err::Error(Error::from_error_kind(input.clone(), ErrorKind::Fail)))?;
50
51 let binding = source_content.clone();
52 #[allow(clippy::let_and_return)]
53 let x = match cut(parse_kconfig)(KconfigInput::new_extra(
54 &binding,
55 source_kconfig_file.clone(),
56 )) {
57 Ok((_, kconfig)) => Ok((input, kconfig)),
58 Err(_e) => Err(nom::Err::Error(nom::error::Error::new(
59 KconfigInput::new_extra("", source_kconfig_file),
60 ErrorKind::Fail,
61 ))),
62 };
63 x
64}
65
66fn is_dynamic_source(file: &str) -> bool {
67 let re = Regex::new("\\$(.+)").unwrap();
68 re.is_match(file)
69}
70
71pub type Source = Kconfig;