use nom::{
branch::alt,
bytes::complete::tag,
combinator::map,
multi::many0,
sequence::{delimited, pair},
IResult, Parser,
};
#[cfg(feature = "coreboot")]
use nom::{
character::complete::{alphanumeric1, one_of},
combinator::recognize,
multi::many1,
};
#[cfg(feature = "deserialize")]
use serde::Deserialize;
#[cfg(feature = "serialize")]
use serde::Serialize;
use crate::{
attribute::{optional::parse_optional, parse_attribute, r#type::parse_type, Attribute},
util::ws,
Entry, KconfigInput,
};
use super::parse_entry;
#[derive(Debug, Clone, Default, PartialEq)]
#[cfg_attr(feature = "hash", derive(Hash))]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct Choice {
#[cfg(feature = "coreboot")]
pub name: Option<String>,
pub options: Vec<Attribute>,
pub entries: Vec<Entry>,
}
fn parse_choice_attributes(input: KconfigInput) -> IResult<KconfigInput, Vec<Attribute>> {
ws(many0(alt((
parse_attribute,
parse_type,
map(ws(parse_optional), |_| Attribute::Optional),
))))
.parse(input)
}
#[cfg(feature = "coreboot")]
pub fn parse_choice_for_coreboot(input: KconfigInput) -> IResult<KconfigInput, Choice> {
map(
delimited(
tag("choice"),
(
map(
recognize(ws(many1(alt((alphanumeric1, recognize(one_of("._"))))))),
|c: KconfigInput| c.trim().to_string(),
),
parse_choice_attributes,
many0(ws(parse_entry)),
),
ws(tag("endchoice")),
),
|(name, options, entries)| Choice {
options,
entries,
name: Some(name),
},
)
.parse(input)
}
fn parse_choice_simple(input: KconfigInput) -> IResult<KconfigInput, Choice> {
map(
delimited(
tag("choice"),
pair(parse_choice_attributes, many0(ws(parse_entry))),
ws(tag("endchoice")),
),
|(options, entries)| {
#[cfg(feature = "coreboot")]
return Choice {
options,
entries,
name: None,
};
#[cfg(not(feature = "coreboot"))]
return Choice { options, entries };
},
)
.parse(input)
}
pub fn parse_choice(input: KconfigInput) -> IResult<KconfigInput, Choice> {
alt((
parse_choice_simple,
#[cfg(feature = "coreboot")]
parse_choice_for_coreboot,
))
.parse(input)
}