Основное правило: Правило делает (а) межсетевой экран компиляции (б) приведение атрибутов. Если вам нужно, используйте правило.
чаю Boost Spirit, написав анализатор, который анализирует два варианта шестнадцатеричного числа, используемого NAMS:
Шестнадцатеричное число с любым суффиксом0x
/0h
или префиксh
/x
.Шестнадцатеричный номер с префиксом$
и должен сопровождатьсядесятичный цифра.Вот то, что я придумал до сих пор и сColiru Session:
//#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/support_extended_variant.hpp>
namespace x3 = boost::spirit::x3;
namespace ast {
struct hex_data : std::string {};
struct pascal_hex_data : std::string {};
struct declared_data : boost::spirit::extended_variant<hex_data, pascal_hex_data>
{
declared_data () : base_type () { std::cout << "ctor default\n"; }
declared_data (hex_data const& rhs) : base_type (rhs) { std::cout << "ctor hex: " << rhs << "\n"; }
declared_data (pascal_hex_data const& rhs) : base_type (rhs) { std::cout << "ctor pascal: " << rhs << "\n"; }
};
} // namespace ast
typedef x3::rule<struct hex_digits_class, std::string> hex_digit_type;
typedef x3::rule<struct hex_data_class, ast::hex_data> hex_data_type;
typedef x3::rule<struct pascalhex_data_class, ast::pascal_hex_data> pascalhex_data_type;
typedef x3::rule<struct declared_data_class, ast::declared_data> declared_data_type;
const hex_data_type hex_data = "hex_data";
const hex_digit_type hex_digit = "hex_digit";
const pascalhex_data_type pascalhex_data = "pascal_hex_data";
const declared_data_type declared_data = "declared_data";
auto const hex_digit_def =
= x3::skip(x3::char_('_'))
[
x3::no_case
[
x3::char_ ('0', '9') | x3::char_ ("a", "f")
]
]
;
auto const hex_data_def
= x3::no_case[x3::lit ("0h") | "0x"] >> +hex_digit_def
| +hex_digit_def >> x3::no_case[x3::lit ("h") | "x"]
;
auto const pascalhex_data_def
= x3::lit ("$") >> x3::char_ ('0', '9') >> +hex_digit_def;
auto const declared_data_def
= hex_data_def
| pascalhex_data_def
;
BOOST_SPIRIT_DEFINE (hex_digit, hex_data, pascalhex_data, declared_data)
struct Visitor
{
using result_type = std::string;
std::string operator()(ast::hex_data const & v) const { return "hex_data"; }
std::string operator()(ast::pascal_hex_data const & v) const { return "pascal_hex_data"; }
};
int main()
{
std::string input = "$9";
ast::declared_data parsed;
bool r =
x3::parse (input.begin (), input.end (),
declared_data_def,
parsed);
std::cout << "r = " << r << "\n";
Visitor v;
std::cout << "result = " << boost::apply_visitor(v, parsed) << "\n";
}
Тем не менее, правилоpascalhex_data_def
не компилируется с сообщением об ошибке, которое выглядит так, как будто дух выводит атрибут правила как фьюжн-кортежchar
а такжеvector
изvariant
даже если указано, что правило имеет атрибут ast, полученный изstring
:
typedef x3::rule<struct pascalhex_data_class, ast::pascal_hex_data> pascalhex_data_type;
Кто-нибудь может указать, почему атрибут, определяемый boost, не соответствует указанному? Во всяком случае, чтобы заставить правило генерировать строку, а неtuple
буст пытается вернуться?