правила, работающие над 1.46 boost :: spirit и перестали работать над повышающим духом 1.55

63
5

constant_double_quotation_string %= char_( '"' ) >> 
*( spirit::qi::string( "\\\"" )[ _val += _1 ] |
( char_ - '"' ) ) >> char_( '"' );

constant_single_quotation_string %= char_( '\'' ) >>
*( spirit::qi::string( "\\\'" )[ _val += _1 ] |
( char_ - '\'' ) ) >> char_( '\'' );

теперь он говорит, что char не является классом или структурой или типом объединения с gcc 4.7.2?

спросил(а) 2021-01-25T19:31:29+03:00 4 месяца, 2 недели назад
1
Решение
63

Разработка моего предыдущего ответа

В случае, если вы действительно хотите разоблачить неопределенное значение, я бы предложил:

    не используя raw (очевидно, потому что мы не хотим отражать точную последовательность ввода в присутствии экранированных символов) все еще не используются семантические действия вместо того, чтобы играть умным с lit('\\') чтобы совместить escape-символ, не добавляя его в выходную последовательность.

Здесь я решил использовать определение одного правила как для синтаксических анализаторов double-, так и для одиночных кавычек. Вместо этого я передаю ожидаемый символ кавычки как унаследованный атрибут:

qi::rule<It, std::string(char)> 
q_literal;

q_literal = lit(_r1) >> *('\\' >> char_ | (char_ - lit(_r1))) >> lit(_r1);
start = q_literal('"') | q_literal('\'');

демонстрация

Live On Coliru

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

namespace qi = boost::spirit::qi;

template <typename It, typename Skipper = qi::space_type>
struct my_grammar : qi::grammar<It, std::string(), Skipper> {

my_grammar() : my_grammar::base_type(start) {
using namespace qi;

start = q_literal('"') | q_literal('\'');

q_literal = lit(_r1) >> *('\\' >> char_ | (char_ - lit(_r1))) >> lit(_r1);

BOOST_SPIRIT_DEBUG_NODES( (start)(q_literal) )
}

private:
qi::rule<It, std::string(), Skipper> start;

// drop skipper to make these rules implicitly 'lexeme'
// see: https://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965
qi::rule<It, std::string(char)> q_literal;
};

int main() {
using It = std::string::const_iterator;
my_grammar<It> g;

for (std::string const& input : {
"\"hello world\"",
"\"hello \\\"world\\\"\"",
"'bye world'",
"'bye \"\\'world\\'\"'",
"bogus" })
{
std::cout << "\n------- Parsing: " << input << '\n';
It f = input.begin(), l = input.end();

std::string result;
bool ok = qi::phrase_parse(f, l, g, qi::space, result);

if (ok)
std::cout << "Parse success: " << result << "\n";
else
std::cout << "Parse failed\n";

if (f!=l)
std::cout << "Remaining unparsed input '" << std::string(f,l) << "'\n";
}
}

Печать неэкранированных литералов:

------- Parsing: "hello world"
Parse success: hello world

------- Parsing: "hello \"world\""
Parse success: hello "world"

------- Parsing: 'bye world'
Parse success: bye world

------- Parsing: 'bye "\'world\'"'
Parse success: bye "'world'"

------- Parsing: bogus
Parse failed
Remaining unparsed input 'bogus'

ответил(а) 2021-01-25T19:31:29+03:00 4 месяца, 2 недели назад
63

Вы даже не указываете объявленный тип правила constant_single_quotation_string.

Здесь некоторые наблюдения и рабочий подход:

Поскольку вы

    по-видимому, не хотят, чтобы значение синтезированного атрибута являлось невыполненной входной последовательностью, вы можете просто использовать директиву qi::raw[] для непосредственного зеркального отображения входной последовательности. Таким образом, вы можете упростить само правило

    Вам не требуется %= (автоматическое назначение правил) или семантические действия ([_val+=_1]); ¹

    Вместо этого, если вы, например, не хотите, чтобы кавычки открытия/закрытия были частью атрибута, просто замените qi::char_('"') на qi::lit('"') (или, действительно, просто '"')

Упрощенная:

qi::rule<It, std::string()> 
dq_literal,
sq_literal;

dq_literal = raw [ '"' >> *("\\\"" | ~char_('"')) >> '"' ];
sq_literal = raw [ "'" >> *("\\'" | ~char_("'")) >> "'" ];

Полная демонстрация


Live On Coliru

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

namespace qi = boost::spirit::qi;

template <typename It, typename Skipper = qi::space_type>
struct my_grammar : qi::grammar<It, std::string(), Skipper> {

my_grammar() : my_grammar::base_type(start) {
using namespace qi;

start = dq_literal
| sq_literal;

dq_literal = raw [ '"' >> *("\\\"" | ~char_('"')) >> '"' ];
sq_literal = raw [ "'" >> *("\\'" | ~char_("'")) >> "'" ];

BOOST_SPIRIT_DEBUG_NODES(
(start)(dq_literal)(sq_literal)
)
}

private:
qi::rule<It, std::string(), Skipper> start;

// drop skipper to make these rules implicitly 'lexeme'
// see: https://stackoverflow.com/questions/17072987/boost-spirit-skipper-issues/17073965#17073965
qi::rule<It, std::string()>
dq_literal,
sq_literal;
};

int main() {
using It = std::string::const_iterator;
my_grammar<It> g;

for (std::string const& input : {
"\"hello world\"",
"\"hello \\\"world\\\"\"",
"'bye world'",
"'bye \"\\'world\\'\"'",
"bogus" })
{
std::cout << "\n------- Parsing: " << input << '\n';
It f = input.begin(), l = input.end();

std::string result;
bool ok = qi::phrase_parse(f, l, g, qi::space, result);

if (ok)
std::cout << "Parse success: " << result << "\n";
else
std::cout << "Parse failed\n";

if (f!=l)
std::cout << "Remaining unparsed input '" << std::string(f,l) << "'\n";
}
}

Печать:

------- Parsing: "hello world"
Parse success: "hello world"

------- Parsing: "hello \"world\""
Parse success: "hello \"world\""

------- Parsing: 'bye world'
Parse success: 'bye world'

------- Parsing: 'bye "\'world\'"'
Parse success: 'bye "\'world\'"'

------- Parsing: bogus
Parse failed
Remaining unparsed input 'bogus'

¹ см. Также Boost Spirit: "Семантические действия злы"?

ответил(а) 2021-01-25T19:31:29+03:00 4 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема