对于字母数字,我有一个lexeme。
attributes = lexeme [+(boost :: spirit :: qi :: alpha | boost :: spirit :: qi :: digit)];
我希望有一个语法规则可以跳过任何其他不符合此规则的字符,只需将这些字符放在矢量中即可。
例如:输入:STR1 + STR2%STR3()STR4 = STR5 + STR6
output: (STR1, STR2, STR3, STR4, STR6)
我尝试了下面的语法,但是在解析字符串中的第一个单词后它会跳过所有内容。如何按照我的描述将其更改为解析?
typedef std::vector<std::wstring> Attributes;
template <typename It, typename Skipper=boost::spirit::qi::space_type>
struct AttributeParser : boost::spirit::qi::grammar<It, Attributes(), Skipper>
{
AttributeParser() : AttributeParser::base_type(expression)
{
expression =
*( attributes [phx::push_back(qi::_val, qi::_1)])
>> qi::omit[*qi:char_]
;
attributes = qi::lexeme[+(boost::spirit::qi::alpha|qi::boost::spirit::qi::digit)];
BOOST_SPIRIT_DEBUG_NODE(expression);
BOOST_SPIRIT_DEBUG_NODE(attributes);
}
private:
boost::spirit::qi::rule<It, std::wstring() , Skipper> attributes;
boost::spirit::qi::rule<It, Attributes() , Skipper> expression;
};
答案 0 :(得分:2)
我真的会写下你描述的内容:
std::vector<std::wstring> parsed;
bool ok = qi::phrase_parse(
begin(input), end(input),
*qi::lexeme [ +qi::alnum ],
~qi::alnum,
parsed);
即:
parsed
向量这是完整的程序
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
int main()
{
std::wstring input = L"STR1 + STR2 % STR3 () STR4 = STR5+ STR6";
std::vector<std::wstring> parsed;
bool ok = qi::phrase_parse(begin(input), end(input),
*qi::lexeme [ +qi::alnum ],
~qi::alnum,
parsed);
for(auto& v : parsed)
std::wcout << v << std::endl;
}
打印
STR1
STR2
STR3
STR4
STR5
STR6
答案 1 :(得分:1)
在这里,您要解析第一个字符串并将其推入向量:
*( attributes [phx::push_back(qi::_val, qi::_1)])
接下来,您将省略任何可以转换为 char 的内容:
>> qi::omit[*qi:char_]
所以你基本上告诉你的解析器跳过字符串的其余部分,无论字符是否为字母数字。如果您希望它工作,您需要更改
qi::omit[*qi::char_]
类似
qi::omit[*(qi::char_ - qi::alnum)].
并且应该省略除字母数字之外的任何字符,这应该是您要保留的下一个字符串的开头。我现在无法尝试代码,但你明白了。
答案 2 :(得分:0)
除非你致力于使用Spirit(例如,这只是使用Spirit的一小部分,否则),我会用自定义ctype facet来做这件事。
struct alpha_num: std::ctype<char> {
alpha_num(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
// As far as we care, everything is white-space:
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
// except digits and letters:
std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
std::fill(&rc['a'], &rc['z'], std::ctype_base::alpha);
std::fill(&rc['A'], &rc['Z'], std::ctype_base::alpha);
return &rc[0];
}
};
从那里开始,打开文件,使用该ctype facet创建一个区域设置,并读取令牌,这是一个相当简单的问题。这是您输入的快速测试:
int main() {
std::istringstream infile("STR1 + STR2 % STR3 () STR4 = STR5+ STR6");
infile.imbue(std::locale(std::locale(), new alpha_num));
// Initialize vector from file:
std::vector<std::string> tokens((std::istream_iterator<std::string>(infile)),
std::istream_iterator<std::string>());
// show the tokens:
for (auto const & s : tokens)
std::cout << s << "\n";
return 0;
}
结果:
STR1
STR2
STR3
STR4
STR5
STR6