📄 traverse_tests.cpp
字号:
);
assert(c == 'b');
}
///////////////////////////////////////////////////////////////////////////////
//
// The following is a tracing identity_transform traverse metafunction
//
///////////////////////////////////////////////////////////////////////////////
class trace_identity_transform
: public transform_policies<trace_identity_transform> {
public:
typedef trace_identity_transform self_t;
typedef transform_policies<trace_identity_transform> base_t;
template <typename ParserT, typename EnvT>
typename parser_traversal_plain_result<self_t, ParserT, EnvT>::type
generate_plain(ParserT const &parser_, EnvT const &env) const
{
OSSTREAM strout;
strout
<< EnvT::node
<< ": plain ("
<< EnvT::level << ", "
<< EnvT::index
<< "): "
<< parser_name(parser_);
traces.push_back(GETSTRING(strout));
return this->base_t::generate_plain(parser_, env);
}
template <typename UnaryT, typename SubjectT, typename EnvT>
typename parser_traversal_unary_result<self_t, UnaryT, SubjectT, EnvT>::type
generate_unary(UnaryT const &unary_, SubjectT const &subject_,
EnvT const &env) const
{
OSSTREAM strout;
strout
<< EnvT::node << ": unary ("
<< EnvT::level
<< "): "
<< parser_name(unary_);
traces.push_back(GETSTRING(strout));
return this->base_t::generate_unary(unary_, subject_, env);
}
template <typename ActionT, typename SubjectT, typename EnvT>
typename parser_traversal_action_result<self_t, ActionT, SubjectT, EnvT>::type
generate_action(ActionT const &action_, SubjectT const &subject_,
EnvT const &env) const
{
OSSTREAM strout;
strout
<< EnvT::node << ": action("
<< EnvT::level
<< "): "
<< parser_name(action_);
traces.push_back(GETSTRING(strout));
return this->base_t::generate_action(action_, subject_, env);
}
template <typename BinaryT, typename LeftT, typename RightT, typename EnvT>
typename parser_traversal_binary_result<self_t, BinaryT, LeftT, RightT, EnvT>::type
generate_binary(BinaryT const &binary_, LeftT const& left_,
RightT const& right_, EnvT const &env) const
{
OSSTREAM strout;
strout
<< EnvT::node << ": binary("
<< EnvT::level
<< "): "
<< parser_name(binary_);
traces.push_back(GETSTRING(strout));
return this->base_t::generate_binary(binary_, left_, right_, env);
}
std::vector<string> const &get_output() const { return traces; }
private:
mutable std::vector<std::string> traces;
};
template <typename ParserT>
void
post_order_trace_test(ParserT const &parser_, char const *first[], size_t cnt)
{
// traverse
trace_identity_transform trace_vector;
post_order::traverse(trace_vector, parser_);
// The following two re-find loops ensure, that both string arrays contain the
// same entries, only their order may differ. The differences in the trace
// string order is based on the different parameter evaluation order as it is
// implemented by different compilers.
// re-find all trace strings in the array of expected strings
std::vector<std::string>::const_iterator it = trace_vector.get_output().begin();
std::vector<std::string>::const_iterator end = trace_vector.get_output().end();
assert(cnt == trace_vector.get_output().size());
for (/**/; it != end; ++it)
{
if (std::find(first, first + cnt, *it) == first + cnt)
cerr << "node in question: " << *it << endl;
assert(std::find(first, first + cnt, *it) != first + cnt);
}
// re-find all expected strings in the vector of trace strings
std::vector<std::string>::const_iterator begin = trace_vector.get_output().begin();
char const *expected = first[0];
for (size_t i = 0; i < cnt; expected = first[++i])
{
if (std::find(begin, end, std::string(expected)) == end)
cerr << "node in question: " << expected << endl;
assert(std::find(begin, end, std::string(expected)) != end);
}
}
#define _countof(x) (sizeof(x)/sizeof(x[0]))
void
traverse_trace_tests()
{
const char *test_result1[] = {
"0: plain (1, 0): chlit('a')",
"1: plain (1, 1): chlit('b')",
"2: binary(0): sequence[chlit('a'), chlit('b')]",
};
post_order_trace_test(
ch_p('a') >> 'b',
test_result1, _countof(test_result1)
);
char c = 0;
// test: ((a >> b) >> c) >> d
const char *test_result2[] = {
"0: plain (4, 0): chlit('a')",
"1: unary (3): kleene_star[chlit('a')]",
"2: plain (4, 1): chlit('b')",
"3: action(3): action[chlit('b')]",
"4: binary(2): sequence[kleene_star[chlit('a')], action[chlit('b')]]",
"5: plain (2, 2): chlit('c')",
"6: binary(1): sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], chlit('c')]",
"7: plain (2, 3): chlit('d')",
"8: unary (1): optional[chlit('d')]",
"9: binary(0): sequence[sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], chlit('c')], optional[chlit('d')]]",
};
post_order_trace_test(
((*ch_p('a') >> ch_p('b')[assign_a(c)]) >> 'c') >> !ch_p('d'),
test_result2, _countof(test_result2)
);
// test: (a >> (b >> c)) >> d
const char *test_result3[] = {
"0: plain (3, 0): chlit('a')",
"1: unary (2): kleene_star[chlit('a')]",
"2: plain (4, 1): chlit('b')",
"3: action(3): action[chlit('b')]",
"4: plain (3, 2): chlit('c')",
"5: binary(2): sequence[action[chlit('b')], chlit('c')]",
"6: binary(1): sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], chlit('c')]]",
"7: plain (2, 3): chlit('d')",
"8: unary (1): optional[chlit('d')]",
"9: binary(0): sequence[sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], chlit('c')]], optional[chlit('d')]]",
};
post_order_trace_test(
(*ch_p('a') >> (ch_p('b')[assign_a(c)] >> 'c')) >> !ch_p('d'),
test_result3, _countof(test_result3)
);
// test: a >> (b >> (c >> d))
const char *test_result4[] = {
"0: plain (2, 0): chlit('a')",
"1: unary (1): kleene_star[chlit('a')]",
"2: plain (3, 1): chlit('b')",
"3: action(2): action[chlit('b')]",
"4: plain (3, 2): chlit('c')",
"5: plain (4, 3): chlit('d')",
"6: unary (3): optional[chlit('d')]",
"7: binary(2): sequence[chlit('c'), optional[chlit('d')]]",
"8: binary(1): sequence[action[chlit('b')], sequence[chlit('c'), optional[chlit('d')]]]",
"9: binary(0): sequence[kleene_star[chlit('a')], sequence[action[chlit('b')], sequence[chlit('c'), optional[chlit('d')]]]]",
};
post_order_trace_test(
*ch_p('a') >> (ch_p('b')[assign_a(c)] >> ('c' >> !ch_p('d'))),
test_result4, _countof(test_result4)
);
// test: a >> ((b >> c) >> d)
const char *test_result5[] = {
"0: plain (2, 0): chlit('a')",
"1: unary (1): kleene_star[chlit('a')]",
"2: plain (4, 1): chlit('b')",
"3: action(3): action[chlit('b')]",
"4: plain (3, 2): chlit('c')",
"5: binary(2): sequence[action[chlit('b')], chlit('c')]",
"6: plain (3, 3): chlit('d')",
"7: unary (2): optional[chlit('d')]",
"8: binary(1): sequence[sequence[action[chlit('b')], chlit('c')], optional[chlit('d')]]",
"9: binary(0): sequence[kleene_star[chlit('a')], sequence[sequence[action[chlit('b')], chlit('c')], optional[chlit('d')]]]",
};
post_order_trace_test(
*ch_p('a') >> ((ch_p('b')[assign_a(c)] >> 'c') >> !ch_p('d')),
test_result5, _countof(test_result5)
);
// test: (a >> b) >> (c >> d)
const char *test_result6[] = {
"0: plain (3, 0): chlit('a')",
"1: unary (2): kleene_star[chlit('a')]",
"2: plain (3, 1): chlit('b')",
"3: action(2): action[chlit('b')]",
"4: binary(1): sequence[kleene_star[chlit('a')], action[chlit('b')]]",
"5: plain (2, 2): chlit('c')",
"6: plain (3, 3): chlit('d')",
"7: unary (2): optional[chlit('d')]",
"8: binary(1): sequence[chlit('c'), optional[chlit('d')]]",
"9: binary(0): sequence[sequence[kleene_star[chlit('a')], action[chlit('b')]], sequence[chlit('c'), optional[chlit('d')]]]",
};
post_order_trace_test(
(*ch_p('a') >> ch_p('b')[assign_a(c)]) >> ('c' >> !ch_p('d')),
test_result6, _countof(test_result6)
);
}
///////////////////////////////////////////////////////////////////////////////
//
// Main
//
///////////////////////////////////////////////////////////////////////////////
int
main()
{
traverse_identity_tests();
traverse_trace_tests();
cout << "Tests concluded successfully\n";
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -