Spirit X3 没有抛出期望失败
Spirit X3 not throwing expectation failure
根据文档,它说当我使用 expect 运算符时,当运算符不匹配时我应该得到一个 expectation_failure。我想捕获异常以指示用户错误输入的位置。但似乎我得到了某种包装异常:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::spirit::x3::expectation_failure<__gnu_cxx::__normal_iterator<char*, std::string> > > >'
what(): boost::spirit::x3::expectation_failure
Aborted
我的捕获语句是:
try {
r = parse(iter, end, wctl_parser::entry, root);
} catch (x3::expectation_failure<char const*> const& x) {
std::cout << "Never runs,";
} catch (x3::expectation_failure<std::string::const_iterator> const& e) {
std::cout << "me neither" << std::endl;
}
更新:这是一个展示行为的小程序:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace wccs_parser {
namespace x3 = boost::spirit::x3;
namespace ascii = x3::ascii;
namespace qi = boost::spirit::qi;
struct AstNullProcess;
struct AstChoiceProcess;
using AstAnyProcess = x3::variant<
x3::forward_ast<AstNullProcess>,
x3::forward_ast<AstChoiceProcess>
>;
struct AstNullProcess {};
struct AstChoiceProcess {
AstAnyProcess left;
AstAnyProcess right;
};
} // End namespace
BOOST_FUSION_ADAPT_STRUCT(wccs_parser::AstChoiceProcess, left, right)
namespace wccs_parser {
template <typename T> auto rule = [](const char* name = typeid(T).name()) {
struct _{};
return x3::rule<_, T> {name};
};
template <typename T> auto as = [](auto p) { return rule<T>() = p; };
auto nullProcess = as<AstNullProcess>(x3::omit['0']);
auto const choiceActual = as<AstChoiceProcess> (nullProcess > '+' > nullProcess);
auto const choice = rule<AstAnyProcess> ("choice")
= nullProcess >> !x3::lit('+')
| choiceActual;
auto const entry = x3::skip(ascii::space) [choice];
} //End namespace
namespace x3 = boost::spirit::x3;
int main() {
std::string str("0 + ");
wccs_parser::AstAnyProcess root;
auto iter = str.begin();
auto end = str.end();
bool r = false;
try {
r = parse(iter, end, wccs_parser::entry, root);
} catch (x3::expectation_failure<char const*> const& x) {
std::cout << "Never runs," << std::endl;
} catch (x3::expectation_failure<std::string::const_iterator> const& e) {
std::cout << "me neither" << std::endl;
}
if (r) {
std::cout << str << std::endl << std::endl << " Parses OK: " << std::endl;
std::cout << "\n-------------------------\n";
} else {
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
if (iter != end) std::cout << "Partial match" << std::endl;
return 0;
}
如果您赶上 const_iterator
,您需要确保 const_iterator
是您传递给解析的内容:
std::string const str("0 + ");
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace wccs_parser {
using boost::spirit::x3::variant;
using boost::spirit::x3::forward_ast;
struct AstNullProcess;
struct AstChoiceProcess;
using AstAnyProcess = variant<
forward_ast<AstNullProcess>,
forward_ast<AstChoiceProcess>
>;
struct AstNullProcess {};
struct AstChoiceProcess {
AstAnyProcess left;
AstAnyProcess right;
};
} // End namespace
BOOST_FUSION_ADAPT_STRUCT(wccs_parser::AstChoiceProcess, left, right)
namespace wccs_parser {
namespace x3 = boost::spirit::x3;
using x3::expectation_failure;
template <typename T> auto rule = [](const char* name = typeid(T).name()) {
struct _{};
return x3::rule<_, T> {name};
};
template <typename T> auto as = [](auto p, const char* name = typeid(T).name()) { return rule<T>(name) = p; };
auto nullProcess = as<AstNullProcess>(x3::omit['0'], "nullProcess");
auto const choiceActual = as<AstChoiceProcess> (nullProcess > '+' > nullProcess, "choiceActual");
auto const choice = rule<AstAnyProcess> ("choice")
= nullProcess >> !x3::lit('+')
| choiceActual;
auto const entry = x3::skip(x3::ascii::space) [choice];
}
int main() {
std::string const str("0 + ");
try {
auto iter = str.cbegin();
auto end = str.cend();
wccs_parser::AstAnyProcess root;
bool const r = parse(iter, end, wccs_parser::entry, root);
if (r) {
std::cout << str << "\n\n Parses OK: \n";
std::cout << "\n-------------------------\n";
} else {
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
if (iter != end) {
std::cout << "Partial match, leaving '" << std::string(iter,end) << "'\n";
}
} catch (wccs_parser::expectation_failure<std::string::const_iterator> const& e) {
std::cout << "Expected: " << e.which() << " at '" << std::string(e.where(), str.end()) << "'\n";
return 1;
}
}
版画
Expected: nullProcess at ' '
根据文档,它说当我使用 expect 运算符时,当运算符不匹配时我应该得到一个 expectation_failure。我想捕获异常以指示用户错误输入的位置。但似乎我得到了某种包装异常:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::spirit::x3::expectation_failure<__gnu_cxx::__normal_iterator<char*, std::string> > > >'
what(): boost::spirit::x3::expectation_failure
Aborted
我的捕获语句是:
try {
r = parse(iter, end, wctl_parser::entry, root);
} catch (x3::expectation_failure<char const*> const& x) {
std::cout << "Never runs,";
} catch (x3::expectation_failure<std::string::const_iterator> const& e) {
std::cout << "me neither" << std::endl;
}
更新:这是一个展示行为的小程序:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace wccs_parser {
namespace x3 = boost::spirit::x3;
namespace ascii = x3::ascii;
namespace qi = boost::spirit::qi;
struct AstNullProcess;
struct AstChoiceProcess;
using AstAnyProcess = x3::variant<
x3::forward_ast<AstNullProcess>,
x3::forward_ast<AstChoiceProcess>
>;
struct AstNullProcess {};
struct AstChoiceProcess {
AstAnyProcess left;
AstAnyProcess right;
};
} // End namespace
BOOST_FUSION_ADAPT_STRUCT(wccs_parser::AstChoiceProcess, left, right)
namespace wccs_parser {
template <typename T> auto rule = [](const char* name = typeid(T).name()) {
struct _{};
return x3::rule<_, T> {name};
};
template <typename T> auto as = [](auto p) { return rule<T>() = p; };
auto nullProcess = as<AstNullProcess>(x3::omit['0']);
auto const choiceActual = as<AstChoiceProcess> (nullProcess > '+' > nullProcess);
auto const choice = rule<AstAnyProcess> ("choice")
= nullProcess >> !x3::lit('+')
| choiceActual;
auto const entry = x3::skip(ascii::space) [choice];
} //End namespace
namespace x3 = boost::spirit::x3;
int main() {
std::string str("0 + ");
wccs_parser::AstAnyProcess root;
auto iter = str.begin();
auto end = str.end();
bool r = false;
try {
r = parse(iter, end, wccs_parser::entry, root);
} catch (x3::expectation_failure<char const*> const& x) {
std::cout << "Never runs," << std::endl;
} catch (x3::expectation_failure<std::string::const_iterator> const& e) {
std::cout << "me neither" << std::endl;
}
if (r) {
std::cout << str << std::endl << std::endl << " Parses OK: " << std::endl;
std::cout << "\n-------------------------\n";
} else {
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
if (iter != end) std::cout << "Partial match" << std::endl;
return 0;
}
如果您赶上 const_iterator
,您需要确保 const_iterator
是您传递给解析的内容:
std::string const str("0 + ");
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace wccs_parser {
using boost::spirit::x3::variant;
using boost::spirit::x3::forward_ast;
struct AstNullProcess;
struct AstChoiceProcess;
using AstAnyProcess = variant<
forward_ast<AstNullProcess>,
forward_ast<AstChoiceProcess>
>;
struct AstNullProcess {};
struct AstChoiceProcess {
AstAnyProcess left;
AstAnyProcess right;
};
} // End namespace
BOOST_FUSION_ADAPT_STRUCT(wccs_parser::AstChoiceProcess, left, right)
namespace wccs_parser {
namespace x3 = boost::spirit::x3;
using x3::expectation_failure;
template <typename T> auto rule = [](const char* name = typeid(T).name()) {
struct _{};
return x3::rule<_, T> {name};
};
template <typename T> auto as = [](auto p, const char* name = typeid(T).name()) { return rule<T>(name) = p; };
auto nullProcess = as<AstNullProcess>(x3::omit['0'], "nullProcess");
auto const choiceActual = as<AstChoiceProcess> (nullProcess > '+' > nullProcess, "choiceActual");
auto const choice = rule<AstAnyProcess> ("choice")
= nullProcess >> !x3::lit('+')
| choiceActual;
auto const entry = x3::skip(x3::ascii::space) [choice];
}
int main() {
std::string const str("0 + ");
try {
auto iter = str.cbegin();
auto end = str.cend();
wccs_parser::AstAnyProcess root;
bool const r = parse(iter, end, wccs_parser::entry, root);
if (r) {
std::cout << str << "\n\n Parses OK: \n";
std::cout << "\n-------------------------\n";
} else {
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
if (iter != end) {
std::cout << "Partial match, leaving '" << std::string(iter,end) << "'\n";
}
} catch (wccs_parser::expectation_failure<std::string::const_iterator> const& e) {
std::cout << "Expected: " << e.which() << " at '" << std::string(e.where(), str.end()) << "'\n";
return 1;
}
}
版画
Expected: nullProcess at ' '