Могут ли быть настроены правила повышения духа

В моей грамматике Boost Spirit я хотел бы иметь правило, которое делает это:

правило<…> noCaseLit = no_case [lit («KEYWORD»)];

но для пользовательского ключевого слова, чтобы я мог сделать это:

… >> noCaseLit («SomeSpecialKeyword») >> … >> noCaseLit («OtherSpecialKeyword1»)

Возможно ли это с правилами Boost Spirit и если да, то как?

Постскриптум В качестве примера я использую нечувствительную к регистру вещь, за которой я следую — это параметризацию правил в целом.

Редактирование:
По ссылке, предоставленной ‘sehe’ в комментариях, я смог приблизиться к тому, что хотел, но пока не совсем.

/* Defining the noCaseLit rule */
rule<Iterator, string(string)> noCaseLit = no_case[lit(_r1)];
/* Using the noCaseLit rule */
rule<...> someRule = ... >> noCaseLit(phx::val("SomeSpecialKeyword")) >> ...

Я еще не нашел способ автоматически преобразовать буквенную строку в значение Феникса, чтобы я мог использовать правило следующим образом:

rule<...> someRule = ... >> noCaseLit("SomeSpecialKeyword") >> ...

3

Решение

Самый простой способ — просто создать функцию, которая возвращает ваше правило / парсер. В примере ближе к концу эта страница Вы можете найти способ объявить возвращаемое значение вашей функции. (Такой же Вот в прокомментированном примере).

#include <iostream>
#include <string>
#include <boost/spirit/include/qi.hpp>

namespace ascii = boost::spirit::ascii;
namespace qi = boost::spirit::qi;

typedef boost::proto::result_of::deep_copy<
BOOST_TYPEOF(ascii::no_case[qi::lit(std::string())])
>::type nocaselit_return_type;

nocaselit_return_type nocaselit(const std::string& keyword)
{
return boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)]);
}

//C++11 VERSION EASIER TO MODIFY (AND DOESN'T REQUIRE THE TYPEDEF)
//auto nocaselit(const std::string& keyword) -> decltype(boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)]))
//{
//  return boost::proto::deep_copy(ascii::no_case[qi::lit(keyword)]);
//}int main()
{
std::string test1="MyKeYWoRD";
std::string::const_iterator iter=test1.begin();
std::string::const_iterator end=test1.end();
if(qi::parse(iter,end,nocaselit("mYkEywOrd"))&& (iter==end))
std::cout << "Parse 1 Successful" << std::endl;
else
std::cout << "Parse 2 Failed. Remaining: " << std::string(iter,end) << std::endl;

qi::rule<std::string::const_iterator,ascii::space_type> myrule =
*(
( nocaselit("double") >> ':' >> qi::double_ )
|   ( nocaselit("keyword") >> '-' >> *(qi::char_ - '.') >> '.')
);

std::string test2=" DOUBLE : 3.5 KEYWORD-whatever.Double  :2.5";
iter=test2.begin();
end=test2.end();
if(qi::phrase_parse(iter,end,myrule,ascii::space)&& (iter==end))
std::cout << "Parse 2 Successful" << std::endl;
else
std::cout << "Parse 2 Failed. Remaining: " << std::string(iter,end) << std::endl;return 0;
}
4

Другие решения

Других решений пока нет …