nom_kconfig/attribute/
range.rs1use nom::{
2 branch::alt,
3 bytes::complete::tag,
4 combinator::map,
5 sequence::{pair, preceded},
6 IResult, Parser,
7};
8#[cfg(feature = "deserialize")]
9use serde::Deserialize;
10#[cfg(feature = "serialize")]
11use serde::Serialize;
12#[cfg(feature = "display")]
13use std::fmt::Display;
14
15use super::expression::{parse_if_attribute, Expression};
16use crate::{
17 number::parse_number,
18 symbol::{parse_constant_hex_as_string, parse_non_constant_symbol},
19};
20use crate::{util::ws, KconfigInput};
21
22#[derive(Debug, Clone, PartialEq)]
24#[cfg_attr(feature = "hash", derive(Hash))]
25#[cfg_attr(feature = "serialize", derive(Serialize))]
26#[cfg_attr(feature = "deserialize", derive(Deserialize))]
27pub struct Range {
28 pub lower_bound: RangeBound,
29 pub upper_bound: RangeBound,
30 #[cfg_attr(
31 any(feature = "serialize", feature = "deserialize"),
32 serde(skip_serializing_if = "Option::is_none")
33 )]
34 pub r#if: Option<Expression>,
35}
36
37#[cfg(feature = "display")]
38impl Display for Range {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 match &self.r#if {
41 Some(i) => write!(f, "{} {} if {}", self.lower_bound, self.upper_bound, i),
42 None => write!(f, "{} {}", self.lower_bound, self.upper_bound),
43 }
44 }
45}
46
47fn parse_bounds(input: KconfigInput) -> IResult<KconfigInput, (RangeBound, RangeBound)> {
49 (ws(parse_range_bound), ws(parse_range_bound)).parse(input)
50}
51
52pub fn parse_range(input: KconfigInput) -> IResult<KconfigInput, Range> {
75 map(
76 preceded(ws(tag("range")), pair(ws(parse_bounds), parse_if_attribute)),
77 |((l, r), i)| Range {
78 lower_bound: l,
79 upper_bound: r,
80 r#if: i,
81 },
82 )
83 .parse(input)
84}
85
86#[derive(Debug, Clone, PartialEq)]
87#[cfg_attr(feature = "hash", derive(Hash))]
88#[cfg_attr(feature = "serialize", derive(Serialize))]
89#[cfg_attr(feature = "deserialize", derive(Deserialize))]
90pub enum RangeBound {
91 Hex(String),
92 Number(i64),
93 Symbol(String),
94}
95
96fn parse_range_bound(input: KconfigInput) -> IResult<KconfigInput, RangeBound> {
97 alt((
98 map(parse_constant_hex_as_string, RangeBound::Hex),
99 map(parse_number, RangeBound::Number),
100 map(parse_non_constant_symbol, |s| {
101 RangeBound::Symbol(s.to_string())
102 }),
103 ))
104 .parse(input)
105}
106
107#[cfg(feature = "display")]
108impl Display for RangeBound {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 match self {
111 RangeBound::Hex(h) => write!(f, "{}", h),
112 RangeBound::Number(n) => write!(f, "{}", n),
113 RangeBound::Symbol(s) => write!(f, "{}", s),
114 }
115 }
116}