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