我正在尝试使用boost精神框架来定义自己的语法,并且我正在定义这样一个匹配规则:
value = (
char_('"') >>
(*qi::lexeme[
char_('\\') >> char_('\\') |
char_('\\') >> char_('"') |
graph - char_('"') |
char_(' ')
])[some_func] >>
char_('"')
);
我想将一个动作 - some_func - 分配到它的一部分,并将整个匹配的字符串作为参数传递。但不幸的是,我会得到像vector<boost::variant<boost::fusion::vector2 ..a lot of stuff...)...>
这样的东西。我可以以某种方式将整个数据作为char *,std :: string或甚至void *与大小?
答案 0 :(得分:9)
演示程序的输出:
DEBUG: 'some\\"quoted\\"string.'
parse success
老实说,看起来你真的试图用可能的逃避字符来解析“逐字”字符串。在这方面,使用
lexeme
似乎是错误的(空间被吃掉了)。如果要查看转义字符串解析的示例,请参阅例如
- Boost Spirit Implement small one-line DSL on a server application(此款式)
- Compiling a simple parser with Boost.Spirit(通过复制转发)
- Parsing escaped strings with boost spirit
- Parse quoted strings with boost::spirit
我认为可以做一个简单的重新排列,至少看起来像:
value = qi::lexeme [ char_('"') >> qi::as_string [ *( string("\\\\") | string("\\\"") | (graph | ' ') - '"' ) ] [some_func(_1)] >> char_('"') ];
但是请注意,您可以简单地声明没有队长的规则,然后将
lexeme
全部删除: http://liveworkspace.org/code/1oEhei$0
代码(实时liveworkspace)
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
struct some_func_t
{
template <typename> struct result { typedef void type; };
template <typename T>
void operator()(T const& s) const
{
std::cout << "DEBUG: '" << s << "'\n";
}
};
template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, Skipper>
{
parser() : parser::base_type(value)
{
using namespace qi;
// using phx::bind; using phx::ref; using phx::val;
value = (
char_('"') >>
qi::as_string
[
(*qi::lexeme[
char_('\\') >> char_('\\') |
char_('\\') >> char_('"') |
graph - char_('"') |
char_(' ')
])
] [some_func(_1)] >>
char_('"')
);
BOOST_SPIRIT_DEBUG_NODE(value);
}
private:
qi::rule<It, Skipper> value;
phx::function<some_func_t> some_func;
};
bool doParse(const std::string& input)
{
typedef std::string::const_iterator It;
auto f(begin(input)), l(end(input));
parser<It, qi::space_type> p;
try
{
bool ok = qi::phrase_parse(f,l,p,qi::space);
if (ok)
{
std::cout << "parse success\n";
}
else std::cerr << "parse failed: '" << std::string(f,l) << "'\n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
return ok;
} catch(const qi::expectation_failure<It>& e)
{
std::string frag(e.first, e.last);
std::cerr << e.what() << "'" << frag << "'\n";
}
return false;
}
int main()
{
bool ok = doParse("\"some \\\"quoted\\\" string.\"");
return ok? 0 : 255;
}