nom_kconfig/attribute/expression/
mod.rs

1pub mod atom;
2pub mod compare;
3#[cfg(test)]
4mod mod_test;
5pub mod term;
6
7pub use atom::*;
8pub use compare::*;
9pub use term::*;
10
11#[cfg(feature = "display")]
12use std::fmt::Display;
13
14use nom::{
15    bytes::complete::tag,
16    combinator::{map, opt},
17    multi::many0,
18    sequence::{pair, preceded},
19    IResult, Parser,
20};
21#[cfg(feature = "deserialize")]
22use serde::Deserialize;
23#[cfg(feature = "serialize")]
24use serde::Serialize;
25
26use crate::{util::wsi, KconfigInput};
27
28#[derive(Debug, PartialEq, Clone)]
29#[cfg_attr(feature = "serialize", derive(Serialize))]
30#[cfg_attr(feature = "deserialize", derive(Deserialize))]
31pub enum Operator {
32    And,
33    Or,
34}
35
36// https://stackoverflow.com/questions/9509048/antlr-parser-for-and-or-logic-how-to-get-expressions-between-logic-operators
37pub type Expression = OrExpression;
38#[cfg_attr(feature = "hash", derive(Hash))]
39#[cfg_attr(feature = "serialize", derive(Serialize))]
40#[cfg_attr(feature = "deserialize", derive(Deserialize))]
41#[derive(Debug, PartialEq, Clone)]
42pub enum AndExpression {
43    #[cfg_attr(feature = "serialize", serde(rename = "AndTerm"))]
44    Term(Term),
45    #[cfg_attr(feature = "serialize", serde(rename = "And"))]
46    Expression(Vec<Term>),
47}
48
49#[derive(Debug, PartialEq, Clone)]
50#[cfg_attr(feature = "hash", derive(Hash))]
51#[cfg_attr(feature = "serialize", derive(Serialize))]
52#[cfg_attr(feature = "deserialize", derive(Deserialize))]
53pub enum OrExpression {
54    #[cfg_attr(feature = "serialize", serde(rename = "OrTerm"))]
55    Term(AndExpression),
56    #[cfg_attr(feature = "serialize", serde(rename = "Or"))]
57    Expression(Vec<AndExpression>),
58}
59
60#[cfg(feature = "display")]
61impl Display for AndExpression {
62    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
63        match self {
64            Self::Term(t) => write!(f, "{}", t),
65            Self::Expression(t) => write!(
66                f,
67                "{}",
68                t.iter()
69                    .map(|a| a.to_string())
70                    .collect::<Vec<_>>()
71                    .join(" && ")
72            ),
73        }
74    }
75}
76
77#[cfg(feature = "display")]
78impl Display for OrExpression {
79    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
80        match self {
81            Self::Term(t) => write!(f, "{}", t),
82            Self::Expression(t) => write!(
83                f,
84                "{}",
85                t.iter()
86                    .map(|a| a.to_string())
87                    .collect::<Vec<_>>()
88                    .join(" || ")
89            ),
90        }
91    }
92}
93
94pub fn parse_or_expression(input: KconfigInput) -> IResult<KconfigInput, OrExpression> {
95    map(
96        (
97            wsi(parse_and_expression),
98            many0(preceded(wsi(tag("||")), wsi(parse_and_expression))),
99        ),
100        |(l, ee)| {
101            if ee.is_empty() {
102                OrExpression::Term(l)
103            } else {
104                let mut ll = vec![l];
105                ll.extend(ee);
106                OrExpression::Expression(ll)
107            }
108        },
109    )
110    .parse(input)
111}
112
113pub fn parse_and_expression(input: KconfigInput) -> IResult<KconfigInput, AndExpression> {
114    map(
115        (
116            wsi(parse_term),
117            many0(preceded(wsi(tag("&&")), wsi(parse_term))),
118        ),
119        |(l, ee)| {
120            if ee.is_empty() {
121                AndExpression::Term(l)
122            } else {
123                let mut ll = vec![l];
124                ll.extend(ee);
125                AndExpression::Expression(ll)
126            }
127        },
128    )
129    .parse(input)
130}
131
132pub fn parse_expression(input: KconfigInput) -> IResult<KconfigInput, Expression> {
133    parse_or_expression(input)
134}
135
136pub fn parse_if_attribute(input: KconfigInput) -> IResult<KconfigInput, Option<Expression>> {
137    opt(parse_if_expression).parse(input)
138}
139
140pub fn parse_if_expression(input: KconfigInput) -> IResult<KconfigInput, Expression> {
141    map(pair(wsi(tag("if")), wsi(parse_expression)), |(_, e)| e).parse(input)
142}