133d722a9Sopenharmony_ciuse proc_macro2::Ident;
233d722a9Sopenharmony_ciuse std::mem;
333d722a9Sopenharmony_ciuse syn::parse::{Error, ParseStream, Result};
433d722a9Sopenharmony_ciuse syn::{parenthesized, token, Attribute, LitStr, Token};
533d722a9Sopenharmony_ci
633d722a9Sopenharmony_ci#[derive(Clone)]
733d722a9Sopenharmony_cipub enum CfgExpr {
833d722a9Sopenharmony_ci    Unconditional,
933d722a9Sopenharmony_ci    Eq(Ident, Option<LitStr>),
1033d722a9Sopenharmony_ci    All(Vec<CfgExpr>),
1133d722a9Sopenharmony_ci    Any(Vec<CfgExpr>),
1233d722a9Sopenharmony_ci    Not(Box<CfgExpr>),
1333d722a9Sopenharmony_ci}
1433d722a9Sopenharmony_ci
1533d722a9Sopenharmony_ciimpl CfgExpr {
1633d722a9Sopenharmony_ci    pub fn merge(&mut self, expr: CfgExpr) {
1733d722a9Sopenharmony_ci        if let CfgExpr::Unconditional = self {
1833d722a9Sopenharmony_ci            *self = expr;
1933d722a9Sopenharmony_ci        } else if let CfgExpr::All(list) = self {
2033d722a9Sopenharmony_ci            list.push(expr);
2133d722a9Sopenharmony_ci        } else {
2233d722a9Sopenharmony_ci            let prev = mem::replace(self, CfgExpr::Unconditional);
2333d722a9Sopenharmony_ci            *self = CfgExpr::All(vec![prev, expr]);
2433d722a9Sopenharmony_ci        }
2533d722a9Sopenharmony_ci    }
2633d722a9Sopenharmony_ci}
2733d722a9Sopenharmony_ci
2833d722a9Sopenharmony_cipub fn parse_attribute(attr: &Attribute) -> Result<CfgExpr> {
2933d722a9Sopenharmony_ci    attr.parse_args_with(|input: ParseStream| {
3033d722a9Sopenharmony_ci        let cfg_expr = input.call(parse_single)?;
3133d722a9Sopenharmony_ci        input.parse::<Option<Token![,]>>()?;
3233d722a9Sopenharmony_ci        Ok(cfg_expr)
3333d722a9Sopenharmony_ci    })
3433d722a9Sopenharmony_ci}
3533d722a9Sopenharmony_ci
3633d722a9Sopenharmony_cifn parse_single(input: ParseStream) -> Result<CfgExpr> {
3733d722a9Sopenharmony_ci    let ident: Ident = input.parse()?;
3833d722a9Sopenharmony_ci    let lookahead = input.lookahead1();
3933d722a9Sopenharmony_ci    if input.peek(token::Paren) {
4033d722a9Sopenharmony_ci        let content;
4133d722a9Sopenharmony_ci        parenthesized!(content in input);
4233d722a9Sopenharmony_ci        if ident == "all" {
4333d722a9Sopenharmony_ci            let list = content.call(parse_multiple)?;
4433d722a9Sopenharmony_ci            Ok(CfgExpr::All(list))
4533d722a9Sopenharmony_ci        } else if ident == "any" {
4633d722a9Sopenharmony_ci            let list = content.call(parse_multiple)?;
4733d722a9Sopenharmony_ci            Ok(CfgExpr::Any(list))
4833d722a9Sopenharmony_ci        } else if ident == "not" {
4933d722a9Sopenharmony_ci            let expr = content.call(parse_single)?;
5033d722a9Sopenharmony_ci            content.parse::<Option<Token![,]>>()?;
5133d722a9Sopenharmony_ci            Ok(CfgExpr::Not(Box::new(expr)))
5233d722a9Sopenharmony_ci        } else {
5333d722a9Sopenharmony_ci            Err(Error::new(ident.span(), "unrecognized cfg expression"))
5433d722a9Sopenharmony_ci        }
5533d722a9Sopenharmony_ci    } else if lookahead.peek(Token![=]) {
5633d722a9Sopenharmony_ci        input.parse::<Token![=]>()?;
5733d722a9Sopenharmony_ci        let string: LitStr = input.parse()?;
5833d722a9Sopenharmony_ci        Ok(CfgExpr::Eq(ident, Some(string)))
5933d722a9Sopenharmony_ci    } else if lookahead.peek(Token![,]) || input.is_empty() {
6033d722a9Sopenharmony_ci        Ok(CfgExpr::Eq(ident, None))
6133d722a9Sopenharmony_ci    } else {
6233d722a9Sopenharmony_ci        Err(lookahead.error())
6333d722a9Sopenharmony_ci    }
6433d722a9Sopenharmony_ci}
6533d722a9Sopenharmony_ci
6633d722a9Sopenharmony_cifn parse_multiple(input: ParseStream) -> Result<Vec<CfgExpr>> {
6733d722a9Sopenharmony_ci    let mut vec = Vec::new();
6833d722a9Sopenharmony_ci    while !input.is_empty() {
6933d722a9Sopenharmony_ci        let expr = input.call(parse_single)?;
7033d722a9Sopenharmony_ci        vec.push(expr);
7133d722a9Sopenharmony_ci        if input.is_empty() {
7233d722a9Sopenharmony_ci            break;
7333d722a9Sopenharmony_ci        }
7433d722a9Sopenharmony_ci        input.parse::<Token![,]>()?;
7533d722a9Sopenharmony_ci    }
7633d722a9Sopenharmony_ci    Ok(vec)
7733d722a9Sopenharmony_ci}
78