
рдЕрдЪреНрдЫреЗ рджрд┐рди, рд╕рд╣рдХрд░реНрдорд┐рдпреЛрдВред рдореИрдВ рдЕрднреА рднреА рдПрдХ ISPystem рдбреЗрд╡рд▓рдкрд░ рд╣реВрдВ, рдФрд░ рдореЗрд░рд╛ рдирд╛рдо рдЕрднреА рднреА рджрд┐рдорд┐рддреНрд░реА рд╕реНрдорд┐рд░рдиреЛрд╡ рд╣реИред рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП (рдмрд▓реНрдХрд┐ рд▓рдВрдмреЗ рд╕рдордп рдХреЗ рд▓рд┐рдП) рдореИрдВ рдЕрдЧрд▓реЗ рдкреНрд░рдХрд╛рд╢рди рдХреЗ рд╡рд┐рд╖рдп рдкрд░ рдлреИрд╕рд▓рд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛, рдХреНрдпреЛрдВрдХрд┐ рдмреВрд╕реНрдЯ.рд╕рд┐рдпреЛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдкрд┐рдЫрд▓реЗ рдорд╣реАрдиреЛрдВ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реА рд╕рд╛рдордЧреНрд░реА рдЬрдорд╛ рд╣реЛ рдЧрдИ рд╣реИред рдФрд░ рдЙрд╕ рдкрд▓ рдореЗрдВ рднреА рдЬрдм рдРрд╕рд╛ рд▓рдЧрддрд╛ рдерд╛ рдХрд┐ рдПрдХ рд╕рд┐рдХреНрдХрд╛ рдЙрдЫрд╛рд▓рдирд╛ рдЖрд╕рд╛рди рдерд╛, рдПрдХ рдХрд╛рд░реНрдп рдиреЗ рд╕рдм рдХреБрдЫ рдмрджрд▓ рджрд┐рдпрд╛ред рдПрдХ рдЙрдкрдХрд░рдг рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдерд╛, рдЬреЛ рджреГрд╢реНрдпрдкрдЯрд▓ рдХреЛ рдЕрдиреБрд░реЛрдзрд┐рдд рд╕реВрдЪрд┐рдпреЛрдВ рдореЗрдВ рдбреЗрдЯрд╛ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдмреИрдХрдПрдВрдб рд╕реЗ рд╣реА рд╕реВрдЪреА рдПрдХ рд╕рд╛рдзрд╛рд░рдг json_array рд╣реИред Kat рдореЗрдВ рдЖрдкрдХрд╛ рд╕реНрд╡рд╛рдЧрдд рд╣реИ, рд╣рд╛рд▓ рдХреЗ рджрд┐рдиреЛрдВ рдХреЗ рд╕рднреА рдЙрддрд╛рд░-рдЪрдврд╝рд╛рд╡ рд╣реИрдВред
рддреНрдпрд╛рдЧ
рдореБрдЭреЗ рддреБрд░рдВрдд рдХрд╣рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдкрд┐рдЫрд▓реА рдмрд╛рд░ рд▓реЗрдЦрдХ рдиреЗ "рдорд╣рд╕реВрд╕ рдХрд┐рдпрд╛" рдХреБрдЫ рд╕рд╛рд▓ рдкрд╣рд▓реЗ рд╕рдВрджрд░реНрдн-рдореБрдХреНрдд рд╡реНрдпрд╛рдХрд░рдг рдЬреИрд╕рд╛ рдерд╛ред рддрдм рдРрд╕рд╛ рд▓рдЧрддрд╛ рдерд╛ рдХрд┐ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрдЬрд╛рдп рд╕реНрд▓реЗрдб рдФрд░ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдЙрдкрдХрд░рдг рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рд╕рдорд╕реНрдпрд╛ рдмрдпрд╛рди рдХреЗ рджрд┐рди Boost.Spirit рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реАрдЦрд╛ред
рдХрд╛рд░реНрдп
рдЬреИрд╕реЗ рдХреЛрдИ рдХреНрд╡реЗрд░реА рдЪрд╛рд▓реВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
(string_field CP value AND int_field NOT LT 150) OR bool_field EQ true
рдХреБрдЫ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдЬреЛ рдХрд┐ json рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдЧрд╛ рдФрд░ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░реЗрдЧрд╛ рдХрд┐ рдпрд╣ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред
рдкрд╣рд▓рд╛ рдХрджрдо
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рднрд╡рд┐рд╖реНрдп рдХреЗ рдлрд┐рд▓реНрдЯрд░ рдХреЗ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкрд░ рдирд┐рд░реНрдгрдп рд▓реЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рд░рдгреА рд╕реЗ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдирд┐рдХрд╛рд▓рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдПрд╕рдЯреАрдПрд▓ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ std :: remove_if рдореЗрдВред
рдПрдХ рдлрд╝рдирдХрд╛рд░ рд╕рд╣реА рд╣реЛрдЧрд╛, рдЬреЛ рд╕реАрдзреЗ рд╕рд╛рдордиреЗ рд╕реЗ рдЕрдиреБрд░реЛрдз рд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЪреВрдВрдХрд┐ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдиреЛрд╣рдорди :: json рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдбрд┐рдЬрд╛рдЗрди рдХрд╛рдлреА рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╣реЛрдЧрд╛:
filter = "(string_field CP value AND int_field NOT LT 150) OR bool_field EQ true"; json.erase(std::remove_if(json.begin(), json.end(), std::not_fn(JsonFilter{filter})), json.end());
рдлрд╝рд┐рд▓реНрдЯрд░ рдХреЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдмрд╛рдЗрдирд░реА рдЯреНрд░реА рдореЗрдВ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪреБрдирд╛ред рд╕рдмрд╕реЗ рдХрдо рдХреЛрдиреЗ рдореЗрдВ рддреБрд▓рдирд╛ рдСрдкрд░реЗрдЯрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдмрд╛рдХреА рддрд╛рд░реНрдХрд┐рдХ рдСрдкрд░реЗрдЯрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдЙрдкрд░реЛрдХреНрдд рдлрд╝рд┐рд▓реНрдЯрд░ рдЕрд╕рдВрддреБрд╖реНрдЯ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рджрд┐рдЦреЗрдЧрд╛:

рдкрд░рд┐рдгрд╛рдо рдПрдПрд╕рдЯреА рдХрд╛ рдПрдХ рд░реВрдк рдерд╛, рдпрджрд┐ рдЖрдк рдЗрд╕реЗ рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВред рдЕрдм рдЬрдм рдЖрдЧрд╛рдореА рддрд░реНрдХ рдХреА рддрд╕реНрд╡реАрд░ рдЖрдХрд╛рд░ рд▓реЗ рдЪреБрдХреА рд╣реИ, рддреЛ рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдФрд░ рднрдпрд╛рдирдХ рдХреНрд╖рдг рдЖ рдЧрдпрд╛ рд╣реИред рдпрд╣ рд▓рд┐рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП ... рдЖрддреНрдорд╛ рдкрд░ ...
рдкрд░рд┐рдЪрд┐рдд
рд╕рдмрд╕реЗ рдХрдард┐рди рд╕рд╡рд╛рд▓ рдЙрдарддрд╛ рд╣реИ: рдХрд╣рд╛рдВ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ? рдЕрд╕рд┐рдпреЛ рдХреЗ рд╡рд┐рдкрд░реАрдд, рд╕реНрдкрд┐рд░рд┐рдЯ рд╣реЗрдбрд░ рдкрдврд╝рдиреЗ рд╕реЗ рдХреЛрдИ рд╕реНрдкрд╖реНрдЯ рд╕рдВрдХреЗрдд рдирд╣реАрдВ рдорд┐рд▓рддрд╛ рдерд╛, рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ - "рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЬрд╛рджреВ" рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдмреВрд╕реНрдЯ рдФрд░ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдореЗрдВ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдПрдХ рдЕрдзреНрдпрдпрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬреЛ рдХреБрдЫ рд╕рдордп рдмрд╛рдж рди рдХреЗрд╡рд▓ рдЙрдирдХреЗ рдлрд▓реЛрдВ рдХреЛ рд▓рд╛рдпрд╛, рдмрд▓реНрдХрд┐ рдореЗрд░реА рдЬрд░реВрд░рддреЛрдВ рдХреЗ рдЬрд┐рддрдирд╛ рд╕рдВрднрд╡ рд╣реЛ рдЙрддрдирд╛ рд╕рдорд╛рдзрд╛рди: рдПрдПрд╕рдЯреА рдХреИрд▓рдХреБрд▓реЗрдЯрд░
рдЖрдЗрдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рд╡реНрдпрд╛рдХрд░рдг рдХреЛ рджреЗрдЦреЗрдВ:
рд╡реНрдпрд╛рдХрд░рдг рдХреИрд▓рдХреБрд▓реЗрдЯрд░ class ArithmeticGrammar1 : public qi::grammar<std::string::const_iterator, ASTNodePtr(), qi::space_type> { public: using Iterator = std::string::const_iterator; ArithmeticGrammar1() : ArithmeticGrammar1::base_type(start) { start = (product >> '+' >> start) [qi::_val = phx::new_<OperatorNode<'+'>> (qi::_1, qi::_2)] | product[qi::_val = qi::_1]; product = (factor >> '*' >> product) [qi::_val = phx::new_<OperatorNode<'*'>> (qi::_1, qi::_2)] | factor[qi::_val = qi::_1]; factor = group[qi::_val = qi::_1] | qi::int_[qi::_val = phx::new_<ConstantNode>(qi::_1)]; group %= '(' >> start >> ')'; } qi::rule<Iterator, ASTNodePtr(), qi::space_type> start, group, product, factor; };
рд╡реНрдпрд╛рдХрд░рдг рдХреЛ рдЖрдзрд╛рд░ qi :: рд╡реНрдпрд╛рдХрд░рдг рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╣реИред ASTNodePtr () рдПрдХ рд╕реНрдкрд╖реНрдЯ, рд▓реЗрдХрд┐рди рд╡реНрдпрд╛рдХрд░рдг рдХреА рд╡рд╕реНрддреБ рдореЗрдВ рдЕрдкреЗрдХреНрд╖рд┐рдд рдкрд░рд┐рдгрд╛рдо рдХреА рд╡рд╕реНрддреБ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред
рдПрдПрд╕рдЯреА рдиреЛрдб рдХреИрд▓рдХреБрд▓реЗрдЯрд░ class ASTNode { public: virtual double evaluate() = 0; virtual ~ASTNode() {} }; using ASTNodePtr = ASTNode*; template <char Operator> class OperatorNode : public ASTNode { public: OperatorNode(const ASTNodePtr &left, const ASTNodePtr &right) : left(left) , right(right) {} double evaluate() { if (Operator == '+') return left->evaluate() + right->evaluate(); else if (Operator == '*') return left->evaluate() * right->evaluate(); } ~OperatorNode() { delete left; delete right; } private: ASTNodePtr left, right;
Boost.Phoenix рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдПрдХ рдпрд╛ рдХрдИ рдЧреИрд░-рдЯрд░реНрдорд┐рдирд▓реЛрдВ рд╕реЗ рдПрдХ рддреИрдпрд╛рд░ рдПрдПрд╕рдЯреА рдиреЛрдб рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕реАрдзреЗ рдкрд░рд┐рдгрд╛рдо рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдХреИрд▓рдХреБрд▓реЗрдЯрд░ рдореЗрдВ рдХреНрдпрд╛ рд╣реИ:
start = (product >> '+' >> start)[qi::_val = phx::new_<OperatorNode<'+'>> (qi::_1, qi::_2)] | product[qi::_val = qi::_1];
start - рд╡рд╛рдХреНрдп рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВред рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдмрд┐рдВрджреБред рдЗрд╕реЗ рдЙрддреНрдкрд╛рдж рдХреЗ рдпреЛрдЧ рдФрд░ рдкреНрд░рд╛рд░рдВрдн, рдпрд╛ рдХреЗрд╡рд▓ рдЙрддреНрдкрд╛рдж рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдкреНрд░рддреНрдпреЗрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рд╡рд░реНрдЧ рдХреЛрд╖реНрдардХ рдореЗрдВ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВред рдпрд╣ рд╡рд╣ рдХреНрд░рд┐рдпрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдпрджрд┐ рд╕рдм рдХреБрдЫ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ, рддреЛ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рд╕рдлрд▓ рд╣реЛрдиреЗ рдкрд░ рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдХреНрдпреВрдИ :: _ рд╡реИрд▓ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрдврд╝рд╛рд╡рд╛ рд╣реИ :: рднрд╛рд╡рдирд╛ :: рдХреНрдпреВрдИ :: _ рд╡реИрд▓ рдПрдХ рдкреНрд▓реЗрд╕рд╣реЛрд▓реНрдбрд░ рд╣реИред рдЗрд╕рдХреА рдорджрдж рд╕реЗ, рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рдЬрд╡рд╛рдм рджрд░реНрдЬ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдкреНрд░рд╛рд░рдВрдн рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдПрдХ рдСрдкрд░реЗрдЯрд░-рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдкрд╣рд▓рд╛ рддрд░реНрдХ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдЙрддреНрдкрд╛рдж рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реЛрдЧрд╛, рдФрд░ рджреВрд╕рд░рд╛ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдкреНрд░рд╛рд░рдВрдн рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИред
рд╣рдо рдЖрдЧреЗ рджреЗрдЦрддреЗ рд╣реИрдВред рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдо рджреВрд╕рд░реЗ рд╡рд┐рдХрд▓реНрдк рдкрд░ рдЖрддреЗ рд╣реИрдВ, рддреЛ рдкреНрд░рд╛рд░рдВрдн рдПрдХ рд░рд╛рд╢рд┐ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХ рдЙрддреНрдкрд╛рдж рд╣реИред рдЙрд╕реЗ рдХреИрд╕реЗ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ?
product = (factor >> '*' >> product) [qi::_val = phx::new_<OperatorNode<'*'>> (qi::_1, qi::_2)] | factor[qi::_val = qi::_1];
рдкрд┐рдЫрд▓реА рддрд╕реНрд╡реАрд░ рдХреЛ рдиреНрдпреВрдирддрдо рдЕрдВрддрд░ рдХреЗ рд╕рд╛рде рджреЛрд╣рд░рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдлрд┐рд░ рд╕реЗ рд╣рдо рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреА рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдкреВрд░рд╛ рдХрд░рддреЗ рд╣реИрдВ, рдлрд┐рд░ рд╕реЗ рд╣рдо рдкрд░рд┐рдгрд╛рдо рдореЗрдВ OperatorNode рдСрдмреНрдЬреЗрдХреНрдЯ рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рдпрд╛ рдмрд╕ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ рдХрд╛рд░рдХред рдЖрдЗрдП рдЗрд╕реЗ рджреЗрдЦреЗрдВред
factor = group[qi::_val = qi::_1] | qi::int_[qi::_val = phx::new_<ConstantNode>(qi::_1)];
рдЬреИрд╕реЗ рд╣реА рд╣рдо рд╕рдмрд╕реЗ рдЫреЛрдЯреЗ рд░рд╛рд╕реНрддреЗ рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ, рд╣рдо рдорд╛рди рд▓реЗрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдЗрдВрдЯ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХрд┐рд╕реА рд╕реЗ рдирд╣реАрдВ рдорд┐рд▓реЗред рдЕрдм, рдпрджрд┐ рд╣рдо рдЫрджреНрдо рдХреЛрдб рдХреЗ рд╕рднреА рдкрд┐рдЫрд▓реЗ рдЪрд░рдгреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдПрдХ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд░реВрдк рдореЗрдВ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ:
factor1 = ConstantNode(1)
рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдб, рдКрдкрд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ (рд╕рдмрд╕реЗ рдХрдо рд╡рд╛рд▓реЗ рдХреЛ рдЫреЛрдбрд╝рдХрд░, рдЬреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдпрд╣рд╛рдВ рдкреВрд░реНрдгрд╛рдВрдХ рд╣реИрдВ), рдмрд╛рдж рдХреЗ рдиреЛрдбреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдореВрд▓ рддрддреНрд╡ рдкрд░ рдореВрд▓реНрдпрд╛рдВрдХрди () рд╡рд┐рдзрд┐ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рдХреЙрд▓ рдкреВрд░реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ, рдЕрджреНрднреБрдд!
рддрдм qi :: space_type рдЖрдкрдХреА рдЖрдВрдЦ рдХреЛ рдкрдХрдбрд╝рддрд╛ рд╣реИ - рдпрд╣ рддрд░реНрдХ рдкрд╛рд░реНрд╕ рдХрд░рддреЗ рд╕рдордп рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд┐рдП рдЧрдП рддрддреНрд╡реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИред рдпрд╣ рдЕрднреА рднреА рдореБрдЭ рдкрд░ рдПрдХ рдЪрд╛рд▓ рдЦреЗрд▓реЗрдВрдЧреЗ :-)ред
рдпрд╣рд╛рдВ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЙрддреНрдкрд╛рдж (*) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдиреЙрдирдЯрд░реНрдорд┐рдирд▓ рд╕реНрдЯрд╛рд░реНрдЯ (рдмрд╕ рдпреБрдХреНрдд +) рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рдХреЗ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдЧреБрдгрд╛ рдХреЛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджреЗрдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рд╣реИред рдореЗрд░реЗ рд╡реНрдпрд╛рдХрд░рдг рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдХрд┐ рдФрд░ рдкрд░ рд╣рд╛рд╡реА рд╣реЛрдЧрд╛ рдпрд╛, рдореИрдВ рдмрд╕ рд╕рд╣реА рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рддрд╛рд░реНрдХрд┐рдХ рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реВрдВред рдпрджрд┐ рдЧрдгрд┐рддреАрдп рдСрдкрд░реЗрдЯрд░реЛрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдореЗрдВ рдЧрд▓рддреА рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ, рддреЛ рдкрд╛рда рддрд╛рд░реНрдХрд┐рдХ рддрд╛рд░реНрдХрд┐рдХ рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рдХрд╣рд╛рдиреА рд╣реИред рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рдХрдо рд╕реЗ рдХрдо рднрд╛рдЧ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдЗрдЪреНрдЫрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд░рдЬрд┐рд╕реНрдЯрд░ред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдЖрддреНрдорд╛ рдореЗрдВ рдПрдХ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдкреНрд░рдХрд╛рд░ qi :: no_case рд╣реИ
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рдмрдЬрд╛рдп, рдореБрдЭреЗ рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЗ рдирд╛рдореЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдЗрд╕рд▓рд┐рдП рд╣рдо рдмрд┐рд▓реНрдЯ-рдЗрди qi :: int_ рд╕реНрдкрд┐рд░рд┐рдЯ рдХреЗ рдмрдЬрд╛рдп рд╕рдВрдмрдВрдзрд┐рдд рдиреЙрдирдЯрд░реНрдорд┐рдирд▓ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ :
field = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
рдФрд░ рд╣рдо рдпрд╣рд╛рдБ рдЗрд╕ рддрд░рд╣ рдХреА рдПрдХ рд╕рд░рд▓ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ (рдЕрдм рддрдХ рдХреЛрдИ рд╢рдмреНрджрд╛рд░реНрде рд╕рдВрдЪрд╛рд▓рди рдирд╣реАрдВ):
start = product >> qi::no_case["OR"] >> start | product; product = factor >> qi::no_case["AND"] >> product | factor; factor = group | field; group %= '(' >> start >> ')';
рдЕрдм рд╕рдм рдХреБрдЫ рд╕рд░рд▓рддрдо рд╡рд╛рдХреНрдп "рдлрд╝реАрд▓реНрдб рдФрд░ рдлрд╝реАрд▓реНрдб 2" рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИред рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ ... рдХреБрдЫ рднреА рдирд╣реАрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╕рдорд╕реНрдпрд╛ рдПрдХ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд╕реНрдерд╛рди рдкрд░ рдереА: рдХреНрдпреВрдИ :: space_type рдХреЗрд╡рд▓ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рдХреА рдЙрдкреЗрдХреНрд╖рд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдпрд╣ рдЙрдиреНрд╣реЗрдВ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╡рд╛рдХреНрдп рд╕реЗ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдлрд╝рд┐рд▓реНрдЯрд░ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдлреЙрд░реНрдо рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдореЗрдВ рдЖрддрд╛ рд╣реИ:
"fieldAndfield2" \\ , "(5 * 5) + 11 " \\ "(5*5)+11"
рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рд╕рд┐рдВрдЧрд▓ рдлреАрд▓реНрдб рд╣реИред рддрджрдиреБрд╕рд╛рд░, рдЖрдкрдХреЛ рдХреБрдЫ рд╕реНрдХрд┐рдкрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
skipper = +qi::lit(' ');
рдЦреЗрддреЛрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рднрд╛рд╡реЛрдВ рд╕реЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рдпрд╣ рд╕рдордЭрдирд╛ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдореВрд▓реНрдп рдХреЗ рдЦрд┐рд▓рд╛рдл рдХреНрд╖реЗрддреНрд░ рдХреЛ рдХреИрд╕реЗ рдорд╛рдиреНрдп рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕рднреА рддреБрд▓рдирд╛ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
enum class Operator { EQ,
рдФрд░ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдЧреИрд░ рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
value = qi::double_ | qi::int_ | qi::bool_ | string; string = qi::lit("'") >> +qi::char_("a-zA-Z0-9_. ") >> qi::lit("'");
рдЕрдм рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдХрд┐ рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдРрд╕рд╛ рддрд░реАрдХрд╛ рд▓рд╛рддрд╛ рд╣реИред рдЖрддреНрдорд╛ рдЗрд╕реЗ рдмрдврд╝рд╛рд╡рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рд▓реМрдЯрд╛рдПрдЧреА :: рд╕рдВрд╕реНрдХрд░рдг <int, double, bool, std :: string> , рдФрд░ рдЬрдм рдХреБрдЫ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдЗрд╕рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рдЖрддрд╛ рд╣реИ, рддреЛ рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдореВрд▓реНрдп рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЯреНрд░рд┐рдХреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рдпрд╣рд╛рдБ рдореЗрд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╡рд┐рдХрд▓реНрдк рд╣реИ:
using ValueType = boost::variant<int, double, bool, std::string>; struct ValueGetter : public boost::static_visitor<Json> { template <typename Type> Json operator()(const Type &value) const { return value; } };
рдПрдХ рдЧреЙрдЯрд░ рдПрдХ рдЬрд╕рди рд╡рд╕реНрддреБ рдХреНрдпреЛрдВ рд▓реМрдЯрд╛рддрд╛ рд╣реИ? рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдХреЗ рджреМрд░рд╛рди рдореВрд▓реНрдпреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╕рдордп, рдореИрдВ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рд╕реЗ рдмрдЪреВрдВрдЧрд╛ рдХрд┐ рдХреМрди рд╕рд╛ рдбреЗрдЯрд╛ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреА рддреБрд▓рдирд╛ рд╕реЗ рдЧреБрдЬрд░ рд░рд╣рд╛ рд╣реИ, рдЬреЛ рд╕рднреА рдХрд╛рдореЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдЬрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдЬрд╛ рд░рд╣рд╛ рд╣реИред
рдлрд┐рдирд┐рд╢ рд▓рд╛рдЗрдиред рдореИрдЪрд░ рдХрд╛ рд╡рд┐рд╡рд░рдг рд╕реНрд╡рдпрдВред рд╣рдо рдПрдХ рдХреИрд▓рдХреБрд▓реЗрдЯрд░ рдХреЗ рд╕рд╛рде рдПрдХ рд╣реА рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдЕрдореВрд░реНрддрддрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рд╣рдо рд╡реНрдпрд╛рдХрд░рдг рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдЖрддреНрдорд╛ рдХреГрдкрдпрд╛ рдЗрд╕реЗ рд╣рдорд╛рд░реЗ рд╕рд╛рде рднрд░ рджреЗрдЧреА:
class AbstractMatcher { public: AbstractMatcher() = default; virtual ~AbstractMatcher() = default; virtual bool evaluate(const Json &object) = 0;
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рддрд╛рд░реНрдХрд┐рдХ рдиреЛрдбреНрд╕ рдореБрдЦреНрдп рдлрд┐рд▓реНрдЯрд░ рдиреЛрдбреНрд╕ рд╣реИрдВ:
рддрд╛рд░реНрдХрд┐рдХ рдиреЛрдб enum class Logic { AND, OR }; template <Logic Operator> class LogicNode final : public AbstractMatcher { public: LogicNode(MatcherPtr &left, MatcherPtr &right) : m_left(std::move(left)) , m_right(std::move(right)) { switch (Operator) { case Logic::AND: m_evaluator = &LogicNode::And; break; case Logic::OR: m_evaluator = &LogicNode::Or; } } bool evaluate(const Json &object) final { return std::invoke(m_evaluator, this, object); } private: MatcherPtr m_left; MatcherPtr m_right; using EvaluateType = bool(LogicNode::*)(const Json &); EvaluateType m_evaluator = nullptr; bool And(const Json &object) { return m_left->evaluate(object) && m_right->evaluate(object); } bool Or(const Json &object) { return m_left->evaluate(object) || m_right->evaluate(object); } };
рдФрд░ рдЕрдВрдд рдореЗрдВ, рдиреАрдЪреЗ рдиреЛрдб
рдорд╛рди рддреБрд▓рдирд╛ class ObjectNode final : public AbstractMatcher { public: ObjectNode(std::string field, const ValueType &value, boost::optional<std::string> &unary, Operator oper) : m_field(std::move(field)) , m_json_value(boost::apply_visitor(ValueGetter(), value)) , m_reject(unary.has_value()) { switch (oper) { case Operator::EQ: m_evaluator = &ObjectNode::Equal; break; case Operator::LT: m_evaluator = &ObjectNode::LesserThan; break; case Operator::GT: m_evaluator = &ObjectNode::GreaterThan; break; case Operator::CP: m_evaluator = &ObjectNode::Substr; break; } } bool evaluate(const Json &object) final { const auto &value = object.at(m_field); const bool result = std::invoke(m_evaluator, this, value); return m_reject ? !result : result; } private: using EvaluateType = bool(ObjectNode::*)(const Json &); const std::string m_field; const Json m_json_value; const bool m_reject; EvaluateType m_evaluator = nullptr; bool Equal(const Json &json) { return json == m_json_value; } bool LesserThan(const Json &json) { return json < m_json_value; } bool GreaterThan(const Json &json) { return json > m_json_value; } bool Substr(const Json &json) { return Str(json).find(Str(m_json_value)) != std::string::npos; } };
рдпрд╣ рдХреЗрд╡рд▓ рдЗрд╕реЗ рдПрдХ рд╕рд╛рде рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╣реА рд░рд╣рддрд╛ рд╣реИ:
рдЬреИрд╕рди рдлрд┐рд▓реНрдЯрд░ struct JsonFilterGrammar : qi::grammar<std::string::const_iterator, MatcherPtr()> { JsonFilterGrammar() : JsonFilterGrammar::base_type(expression) { skipper = +qi::lit(' '); unary = qi::no_case["NOT"]; compare.add ("eq", Operator::EQ) ("lt", Operator::LT) ("gt", Operator::GT) ("cp", Operator::CP); expression = (product >> skipper >> qi::no_case["OR"] >> skipper >> expression) [qi::_val = make_shared_<LogicNode<Logic::OR>>()(qi::_1, qi::_2)] | product[qi::_val = qi::_1]; product = (term >> skipper >> qi::no_case["AND"] >> skipper >> product) [qi::_val = make_shared_<LogicNode<Logic::AND>>()(qi::_1, qi::_2)]| term[qi::_val = qi::_1]; term = group[qi::_val = qi::_1] | (field >> -(skipper >> unary)>> skipper >> qi::no_case[compare] >> skipper >> value) [qi::_val = make_shared_<ObjectNode>()(qi::_1, qi::_4, qi::_2, qi::_3)]; field = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9"); value = qi::double_ | qi::int_ | qi::bool_ | string; string = qi::lit("'") >> +qi::char_("a-zA-Z0-9_. \u20BDтВм$┬е-") >> qi::lit("'"); group %= '(' >> expression >> ')'; } qi::rule<Iterator> skipper; qi::rule<Iterator, MatcherPtr()> product, term, expression, group; qi::rule<Iterator, std::string()> field, unary, string; qi::rule<Iterator, ValueType()> value; qi::symbols<char, Operator> compare;
рд╡рд╣ рд╕рдм рд╣реИред рдЕрдм рд╕рдорд╛рдкреНрдд рдлрд┐рд▓реНрдЯрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рдСрдкрд░реЗрд╢рди рдмрди рдЧрдпрд╛ рд╣реИ:
MatcherPtr matcher; std::string filter = "int not LT 15"; JsonFilterGrammar grammar; qi::parse(filter.begin(), filter.end(), grammar, matcher);
рдореИрдВ рд╡реНрдпрд╛рдХрд░рдг рдХреЛ рдПрдХ рдлрд╝рдирдХрд╛рд░ рдореЗрдВ рд▓рдкреЗрдЯрдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЫреЛрдбрд╝ рджреВрдВрдЧрд╛ (рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрдЧрд╛)ред рд╣рдо рд╕рд░рд▓рддрдо рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреЗрд╣рддрд░ рддрд░реАрдХреЗ рд╕реЗ рдЯреВрд▓ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ:
std::string filter = "int not LT 15"; Json json{ {{"int", 10}}, {{"int", 11}}, {{"int", 20}}, {{"int", 30}}, {{"int", 9}} }; std::cout << json.dump() << std::endl; json.erase(std::remove_if(json.begin(), json.end(), std::not_fn(JsonFilter{filter})), json.end()); std::cout << json.dump() << std::endl;
рдпрд╣рд╛рдБ рдЙрддреНрдкрд╛рджрди рд╣реИ:
[{"int":10},{"int":11},{"int":20},{"int":30},{"int":9}] [{"int":20},{"int":30}]
рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ, рдкреНрд░рд┐рдп рдкрд╛рдардХреЛрдВ, рдЖрдк рдЖрддреНрдорд╛ рдХреЗ рдореВрд▓ рддрддреНрд╡ рдХреЛ рдЬрд╛рдирдиреЗ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдореБрдЭреЗ рднреА рдЬрд╛рдирдиреЗ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рдереЗред рддрдм рдореИрдВ рд░рд╣рддрд╛ рд╣реВрдВред рдЬрд▓реНрдж рдорд┐рд▓рддреЗ рд╣реИрдВред