1use proc_macro2::Ident; 2use std::mem; 3use syn::parse::{Error, ParseStream, Result}; 4use syn::{parenthesized, token, Attribute, LitStr, Token}; 5 6#[derive(Clone)] 7pub enum CfgExpr { 8 Unconditional, 9 Eq(Ident, Option<LitStr>), 10 All(Vec<CfgExpr>), 11 Any(Vec<CfgExpr>), 12 Not(Box<CfgExpr>), 13} 14 15impl CfgExpr { 16 pub fn merge(&mut self, expr: CfgExpr) { 17 if let CfgExpr::Unconditional = self { 18 *self = expr; 19 } else if let CfgExpr::All(list) = self { 20 list.push(expr); 21 } else { 22 let prev = mem::replace(self, CfgExpr::Unconditional); 23 *self = CfgExpr::All(vec![prev, expr]); 24 } 25 } 26} 27 28pub fn parse_attribute(attr: &Attribute) -> Result<CfgExpr> { 29 attr.parse_args_with(|input: ParseStream| { 30 let cfg_expr = input.call(parse_single)?; 31 input.parse::<Option<Token![,]>>()?; 32 Ok(cfg_expr) 33 }) 34} 35 36fn parse_single(input: ParseStream) -> Result<CfgExpr> { 37 let ident: Ident = input.parse()?; 38 let lookahead = input.lookahead1(); 39 if input.peek(token::Paren) { 40 let content; 41 parenthesized!(content in input); 42 if ident == "all" { 43 let list = content.call(parse_multiple)?; 44 Ok(CfgExpr::All(list)) 45 } else if ident == "any" { 46 let list = content.call(parse_multiple)?; 47 Ok(CfgExpr::Any(list)) 48 } else if ident == "not" { 49 let expr = content.call(parse_single)?; 50 content.parse::<Option<Token![,]>>()?; 51 Ok(CfgExpr::Not(Box::new(expr))) 52 } else { 53 Err(Error::new(ident.span(), "unrecognized cfg expression")) 54 } 55 } else if lookahead.peek(Token![=]) { 56 input.parse::<Token![=]>()?; 57 let string: LitStr = input.parse()?; 58 Ok(CfgExpr::Eq(ident, Some(string))) 59 } else if lookahead.peek(Token![,]) || input.is_empty() { 60 Ok(CfgExpr::Eq(ident, None)) 61 } else { 62 Err(lookahead.error()) 63 } 64} 65 66fn parse_multiple(input: ParseStream) -> Result<Vec<CfgExpr>> { 67 let mut vec = Vec::new(); 68 while !input.is_empty() { 69 let expr = input.call(parse_single)?; 70 vec.push(expr); 71 if input.is_empty() { 72 break; 73 } 74 input.parse::<Token![,]>()?; 75 } 76 Ok(vec) 77} 78