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