1f88b2170SEd Tanous #pragma once 2f88b2170SEd Tanous 3f88b2170SEd Tanous #include "filter_expr_parser_ast.hpp" 4f88b2170SEd Tanous 5f88b2170SEd Tanous #include <boost/spirit/home/x3.hpp> 6f88b2170SEd Tanous 7f88b2170SEd Tanous namespace redfish::filter_grammar 8f88b2170SEd Tanous { 9f88b2170SEd Tanous 10f88b2170SEd Tanous // The below rules very intentionally use the same naming as section 7.3.4 of 11f88b2170SEd Tanous // the redfish specification and are declared in the order of the precedence 12f88b2170SEd Tanous // that the standard requires. 13f88b2170SEd Tanous 14f88b2170SEd Tanous namespace details 15f88b2170SEd Tanous { 16f88b2170SEd Tanous using boost::spirit::x3::char_; 17f88b2170SEd Tanous using boost::spirit::x3::int64; 18*2261a982SEd Tanous using boost::spirit::x3::lexeme; 19f88b2170SEd Tanous using boost::spirit::x3::lit; 20f88b2170SEd Tanous using boost::spirit::x3::real_parser; 21f88b2170SEd Tanous using boost::spirit::x3::rule; 22f88b2170SEd Tanous using boost::spirit::x3::strict_real_policies; 23f88b2170SEd Tanous using boost::spirit::x3::symbols; 24f88b2170SEd Tanous 25f88b2170SEd Tanous using filter_ast::BooleanOp; 26f88b2170SEd Tanous using filter_ast::Comparison; 27f88b2170SEd Tanous using filter_ast::ComparisonOpEnum; 28f88b2170SEd Tanous using filter_ast::LogicalAnd; 29f88b2170SEd Tanous using filter_ast::LogicalNot; 30f88b2170SEd Tanous using filter_ast::LogicalOr; 31f88b2170SEd Tanous using filter_ast::QuotedString; 32f88b2170SEd Tanous using filter_ast::UnquotedString; 33f88b2170SEd Tanous 34f88b2170SEd Tanous // Clang format makes a mess of these rules and makes them hard to read 35f88b2170SEd Tanous // clang-format on 36f88b2170SEd Tanous 37f88b2170SEd Tanous // Basic argument types 38f88b2170SEd Tanous const rule<class QuotedStringId, QuotedString> quotedString("QuotedString"); 39f88b2170SEd Tanous const rule<class UnquotedStrId, UnquotedString> unquotedString("UnquotedStr"); 40f88b2170SEd Tanous 41f88b2170SEd Tanous // Value comparisons -> boolean (value eq value) (value lt number) 42f88b2170SEd Tanous const rule<class BooleanOpId, BooleanOp> booleanOp("BooleanOp"); 43f88b2170SEd Tanous const rule<class ComparisonId, Comparison> comparison("Comparison"); 44f88b2170SEd Tanous 45f88b2170SEd Tanous // Logical Comparisons (bool eq bool) 46f88b2170SEd Tanous const rule<class LogicalAndId, LogicalAnd> logicalAnd("LogicalAnd"); 47f88b2170SEd Tanous const rule<class LogicalOrId, LogicalOr> logicalOr("LogicalOr"); 48f88b2170SEd Tanous const rule<class LogicalNotId, LogicalNot> logicalNot("LogicalNot"); 49f88b2170SEd Tanous 50f88b2170SEd Tanous ///// BEGIN GRAMMAR 51f88b2170SEd Tanous 52f88b2170SEd Tanous // Two types of strings. 53*2261a982SEd Tanous const auto quotedString_def = '\'' >> lexeme[*('\\' >> char_ | ~char_('\''))] >> 54*2261a982SEd Tanous '\''; 55f88b2170SEd Tanous const auto unquotedString_def = char_("a-zA-Z") >> *(char_("a-zA-Z0-9[]/")); 56f88b2170SEd Tanous 57f88b2170SEd Tanous // Make sure we only parse true floating points as doubles 58f88b2170SEd Tanous // This requires we have a "." which causes 1 to parse as int64, and 1.0 to 59f88b2170SEd Tanous // parse as double 60f88b2170SEd Tanous constexpr const real_parser<double, strict_real_policies<double>> strictDouble; 61f88b2170SEd Tanous 62f88b2170SEd Tanous // Argument 63f88b2170SEd Tanous const auto arg = strictDouble | int64 | unquotedString | quotedString; 64f88b2170SEd Tanous 65f88b2170SEd Tanous // Greater Than/Less Than/Equals 66f88b2170SEd Tanous const symbols<ComparisonOpEnum> compare{ 67f88b2170SEd Tanous {"gt", ComparisonOpEnum::GreaterThan}, 68f88b2170SEd Tanous {"ge", ComparisonOpEnum::GreaterThanOrEqual}, 69f88b2170SEd Tanous {"lt", ComparisonOpEnum::LessThan}, 70f88b2170SEd Tanous {"le", ComparisonOpEnum::LessThanOrEqual}, 71f88b2170SEd Tanous {"ne", ComparisonOpEnum::NotEquals}, 72f88b2170SEd Tanous {"eq", ComparisonOpEnum::Equals}}; 73f88b2170SEd Tanous 74*2261a982SEd Tanous // Note, unlike most other comparisons, spaces are required here (one or more) 75*2261a982SEd Tanous // to differentiate keys from values (ex Fooeq eq foo) 76*2261a982SEd Tanous const auto comparison_def = 77*2261a982SEd Tanous lexeme[arg >> +lit(' ') >> compare >> +lit(' ') >> arg]; 78f88b2170SEd Tanous 79f88b2170SEd Tanous // Parenthesis 80*2261a982SEd Tanous const auto parens = lit('(') >> logicalAnd >> lit(')'); 81f88b2170SEd Tanous 82f88b2170SEd Tanous // Logical values 83f88b2170SEd Tanous const auto booleanOp_def = comparison | parens; 84f88b2170SEd Tanous 85f88b2170SEd Tanous // Not 86*2261a982SEd Tanous const auto logicalNot_def = -(char_('n') >> lit("ot")) >> booleanOp; 87f88b2170SEd Tanous 88f88b2170SEd Tanous // Or 89*2261a982SEd Tanous const auto logicalOr_def = logicalNot >> *(lit("or") >> logicalNot); 90f88b2170SEd Tanous 91f88b2170SEd Tanous // And 92*2261a982SEd Tanous const auto logicalAnd_def = logicalOr >> *(lit("and") >> logicalOr); 93f88b2170SEd Tanous 94f88b2170SEd Tanous BOOST_SPIRIT_DEFINE(booleanOp, logicalAnd, logicalNot, logicalOr, quotedString, 95f88b2170SEd Tanous comparison, unquotedString); 96f88b2170SEd Tanous ///// END GRAMMAR 97f88b2170SEd Tanous 98f88b2170SEd Tanous // Make the grammar and AST available outside of the system 99f88b2170SEd Tanous static constexpr auto& grammar = logicalAnd; 100f88b2170SEd Tanous using program = filter_ast::LogicalAnd; 101f88b2170SEd Tanous 102f88b2170SEd Tanous } // namespace details 103f88b2170SEd Tanous 104f88b2170SEd Tanous using details::grammar; 105f88b2170SEd Tanous using details::program; 106f88b2170SEd Tanous 107f88b2170SEd Tanous } // namespace redfish::filter_grammar 108