nom_kconfig/entry/
menu.rs1use nom::{
2 branch::alt,
3 bytes::complete::tag,
4 combinator::{cut, map},
5 multi::many0,
6 sequence::{pair, preceded, terminated},
7 IResult,
8};
9#[cfg(feature = "deserialize")]
10use serde::Deserialize;
11#[cfg(feature = "serialize")]
12use serde::Serialize;
13
14use crate::{
15 attribute::{
16 parse_depends_on, parse_prompt_value, parse_visible, visible::Visible, Attribute,
17 Expression,
18 },
19 util::ws,
20 KconfigInput,
21};
22
23use super::{parse_entry, Entry};
24
25#[derive(Debug, Clone, Default, PartialEq)]
27#[cfg_attr(feature = "hash", derive(Hash))]
28#[cfg_attr(feature = "serialize", derive(Serialize))]
29#[cfg_attr(feature = "deserialize", derive(Deserialize))]
30pub struct Menu {
31 pub prompt: String,
32 #[cfg_attr(
33 any(feature = "serialize", feature = "deserialize"),
34 serde(skip_serializing_if = "Option::is_none")
35 )]
36 pub visible: Option<Visible>,
37 pub depends_on: Vec<Expression>,
38 pub entries: Vec<Entry>,
39}
40
41fn parse_menu_attributes(input: KconfigInput) -> IResult<KconfigInput, Vec<Attribute>> {
42 many0(alt((
43 ws(parse_depends_on),
44 map(ws(parse_visible), Attribute::Visible),
45 )))(input)
46}
47
48pub fn parse_menu(input: KconfigInput) -> IResult<KconfigInput, Menu> {
49 let (input, mut menu) = map(
50 preceded(
51 ws(tag("menu")),
52 pair(ws(parse_prompt_value), ws(parse_menu_attributes)),
53 ),
54 |(prompt, attributes)| {
55 let mut menu = Menu {
56 prompt: prompt.to_string(),
57 ..Default::default()
58 };
59 for attribute in attributes {
60 match attribute {
61 Attribute::Visible(a) => menu.visible = Some(a),
62 Attribute::DependsOn(a) => menu.depends_on.push(a),
63 _ => (),
64 }
65 }
66 menu
67 },
68 )(input)?;
69
70 let (input, entries) = cut(terminated(many0(ws(parse_entry)), ws(tag("endmenu"))))(input)?;
71 menu.entries = entries;
72 Ok((input, menu))
73}