1
BNF I實施了一個有趣的規則,根據運營商的不同,這些條款可以是鏈接的或事件不符合此生產規則。因此,我使用同樣的AST數據結構,因爲僅枚舉變化:boost.spirit x3 move_to and list ast member
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <list>
namespace ast
{
struct identifer {
int name;
};
struct expression {
struct chunk {
char operator_;
ast::identifer identifer;
};
ast::identifer identifer;
std::list<chunk> chunk_list;
};
}
BOOST_FUSION_ADAPT_STRUCT(ast::identifer,
name
)
BOOST_FUSION_ADAPT_STRUCT(ast::expression::chunk,
operator_, identifer
)
BOOST_FUSION_ADAPT_STRUCT(ast::expression,
identifer, chunk_list
)
namespace boost { namespace spirit { namespace x3 { namespace traits {
void move_to(ast::expression::chunk&& chunk, std::list<ast::expression::chunk>& chunk_list,
mpl::identity<container_attribute>)
{
chunk_list.emplace(chunk_list.end(), std::move(chunk));
}
} } } }
namespace parser
{
namespace x3 = boost::spirit::x3;
auto const identifier = x3::rule<struct _, int> { "identifier" } =
x3::int_;
auto const operator_1 = x3::rule<struct _, char> { "operator" } =
x3::char_("ABC");
auto const operator_2 = x3::rule<struct _, char> { "operator" } =
x3::char_("XYZ");
auto const expression_chunk_1 = x3::rule<struct _, ast::expression::chunk> { "expression" } =
operator_1 > identifier
;
auto const expression_chunk_2 = x3::rule<struct _, ast::expression::chunk> { "expression" } =
operator_2 > identifier
;
auto const expression = x3::rule<struct _, ast::expression> { "expression" } =
identifier >> *expression_chunk_1 // foo { and foo }
// rule below fails to compile
| identifier >> expression_chunk_2 // foo [ nand foo ]
;
}
struct visitor {
visitor(std::ostream& os) : os{ os } { }
void operator()(ast::expression const& node) {
os << "(";
(*this)(node.identifer);
for(auto const& chunk : node.chunk_list) {
os << "(" << chunk.operator_ << " ";
(*this)(chunk.identifer);
os << ")";
}
os << ")\n";
}
void operator()(ast::identifer const& node) {
os << "(" << node.name << ")";
}
std::ostream& os;
};
int main()
{
namespace x3 = boost::spirit::x3;
for(std::string const str: {
"1 X 2",
"3 A 4 A 5"
}) {
auto iter = str.begin(), end = str.end();
ast::expression attr;
bool r = x3::phrase_parse(iter, end, parser::expression, x3::space, attr);
std::cout << "parse '" << str << "': ";
if (r && iter == end) {
std::cout << "succeeded:\n";
visitor(std::cout)(attr);
} else {
std::cout << "*** failed ***\n";
}
}
return 0;
}
這是想法 - 運營商X,Y,Z只增加一個塊列出。編譯器錯誤後,我必須專門化x3 :: traits :: move_to,但我沒有找到任何解決方案來編譯它。什麼是要做的?是列表:: emplace()和std :: move()在這裏安全嗎?
謝謝 - 解決問題pragamtic方式。這些解決方案編譯如[鏈接](http://coliru.stacked-crooked.com/a/898343ea7611a40a)所示,但解析失敗。只有很小的變化(標識符現在是字符,規則具有唯一的名稱)。通過運行... DEBUG,這是顯而易見的,該標識符被消耗,並且expression_chunk_1必須失敗。一種(可能的)方法是寫 – Olx
如果你告訴我「1×2」的預期結果,你可以在一個新問題中提出這個問題,我想。我看到那不會通過,但看着它,我沒有看到爲什麼它應該通過語法。 – sehe
一個解決問題的實用方法。這些解決方案編譯如[鏈接](http://coliru.stacked-crooked.com/a/898343ea7611a40a)所示,但解析失敗。只有很小的變化(標識符現在是字符,規則具有唯一的名稱)。通過運行... DEBUG,這是顯而易見的,該標識符被消耗,並且expression_chunk_1必須失敗。一種(可能的)方式是編寫 (標識>> >> expression_chunk_1) | (標識符>> x3 :: repeat(1)[expression_chunk_2]) 但由於回溯/展開標識符的迭代器,這並不聰明。 按照下一條評論... – Olx