1 // 2 // Created by Martin Steinegger on 2019-08-20. 3 // 4 #ifndef MMSEQS_TAXONOMYEXPRESSION_H 5 #define MMSEQS_TAXONOMYEXPRESSION_H 6 7 #include "NcbiTaxonomy.h" 8 #include "ExpressionParser.h" 9 10 #include <vector> 11 #include <ctype.h> 12 13 // class need one instance per thread 14 class TaxonomyExpression { 15 public: 16 enum CommaMeaning { 17 COMMA_IS_COMMA, 18 COMMA_IS_OR, 19 COMMA_IS_AND 20 }; 21 22 TaxonomyExpression(const std::string &expression, NcbiTaxonomy &taxonomy, CommaMeaning commaMeaning = COMMA_IS_OR) { 23 std::string bracketExpression; 24 bool inNumber = false; 25 for (size_t i = 0; i < expression.size(); i++) { 26 // make brackets around numbers for tinyexpr 27 const bool isDigit = isdigit(expression[i]); 28 if (isDigit && inNumber == true) { 29 bracketExpression.push_back(expression[i]); 30 } else if (isDigit && inNumber == false) { 31 bracketExpression.append("a("); 32 bracketExpression.push_back(expression[i]); 33 inNumber = true; 34 } else { 35 if (inNumber == true) { 36 bracketExpression.append(")"); 37 inNumber = false; 38 } 39 if (commaMeaning != COMMA_IS_COMMA && expression[i] == ',') { 40 if (commaMeaning == COMMA_IS_OR) { 41 bracketExpression.append("||"); 42 } else if (commaMeaning == COMMA_IS_AND) { 43 bracketExpression.append("&&"); 44 } 45 } else { 46 bracketExpression.push_back(expression[i]); 47 } 48 } 49 } 50 if (inNumber == true) { 51 bracketExpression.append(")"); 52 } 53 tc.t = &taxonomy; 54 te_variable var; 55 var.name = "a"; 56 // GCC 4.8 does not like casting functions to void* 57 // GCC > 4.8 is fine with this 58 #pragma GCC diagnostic push 59 #pragma GCC diagnostic ignored "-Wpedantic" 60 var.address = (const void *) &acst; 61 #pragma GCC diagnostic pop 62 var.type = TE_CLOSURE1; 63 var.context = (void *) &tc; 64 vars.push_back(var); 65 parser = new ExpressionParser(bracketExpression.c_str(), vars); 66 } 67 ~TaxonomyExpression()68 ~TaxonomyExpression() { 69 delete parser; 70 } 71 isAncestor(TaxID taxId)72 bool isAncestor(TaxID taxId) { 73 tc.taxId = taxId; 74 const double result = parser->evaluate(); 75 return (result != 0); 76 } 77 78 private: 79 struct TaxContext { 80 NcbiTaxonomy *t; 81 TaxID taxId; 82 }; 83 TaxContext tc; 84 ExpressionParser *parser; 85 std::vector<te_variable> vars; 86 acst(void * context,double a)87 static double acst(void *context, double a) { 88 TaxContext *o = (TaxContext *) context; 89 bool retVal = o->t->IsAncestor((TaxID) a, o->taxId); 90 return (retVal) ? 1.0 : 0.0; 91 } 92 }; 93 #endif //MMSEQS_TAXONOMYEXPRESSION_H 94