我有这个csv线
std::string s = R"(1997,Ford,E350,"ac, abs, moon","some "rusty" parts",3000.00)";
Run Code Online (Sandbox Code Playgroud)
我可以用boost::tokenizer以下方法解析它:
typedef boost::tokenizer< boost::escaped_list_separator<char> , std::string::const_iterator, std::string> Tokenizer;
boost::escaped_list_separator<char> seps('\\', ',', '\"');
Tokenizer tok(s, seps);
for (auto i : tok)
{
std::cout << i << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
它是正确的,除了令牌"生锈"应该有双引号被剥离.
这是我尝试使用boost :: spirit
boost::spirit::classic::rule<> list_csv_item = !(boost::spirit::classic::confix_p('\"', *boost::spirit::classic::c_escape_ch_p, '\"') | boost::spirit::classic::longest_d[boost::spirit::classic::real_p | boost::spirit::classic::int_p]);
std::vector<std::string> vec_item;
std::vector<std::string> vec_list;
boost::spirit::classic::rule<> list_csv = boost::spirit::classic::list_p(list_csv_item[boost::spirit::classic::push_back_a(vec_item)],',')[boost::spirit::classic::push_back_a(vec_list)];
boost::spirit::classic::parse_info<> result = parse(s.c_str(), list_csv);
if (result.hit)
{
for (auto i : vec_item)
{
cout << i << endl;
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用boost精神框架来定义自己的语法,并且我正在定义这样的匹配规则:
value = (
char_('"') >>
(*qi::lexeme[
char_('\\') >> char_('\\') |
char_('\\') >> char_('"') |
graph - char_('"') |
char_(' ')
])[some_func] >>
char_('"')
);
Run Code Online (Sandbox Code Playgroud)
我想将一个动作 - some_func - 分配到它的一部分,并将整个匹配的字符串作为参数传递.但不幸的是,我会得到类似的东西vector<boost::variant<boost::fusion::vector2 ..a lot of stuff...)...>.我可以以某种方式将整个数据作为char*,std :: string甚至void*与大小?
除了不祥的暗示之外,我找不到任何关于这方面的信息,这可能是完全不可能的,但我不想简单地相信它,因为在这种情况下,惰性解析器似乎毫无用处。我想要做的是在解析时根据之前的一些非终端的结果选择一个解析器。它本质上可以归结为:
static rule<Constant *(Scope &)> &get_constant_parser(Typename type);
rule<Constant *(Scope &, Typename)> constant {
lazy(phoenix::bind(&get_constant_parser, _r2))(_r1)
};
Run Code Online (Sandbox Code Playgroud)
因此get_constant_parser返回适合给定类型名称的解析器,但是该解析器需要类型的参数Scope &。直观上,我会像上面那样写下来,将参数添加到惰性解析器中。然而,这给了我一个无效的表达式:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:177:13: error: static assertion failed: error_invalid_expression
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
^~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
那么如何向惰性解析器提供参数呢?如果确实不可能,那么有人知道为什么吗?
抱歉,这不是一个合适的 MWE,现在我希望有人以前做过并且知道答案。如果您想积极调查并需要 MWE,请告诉我;-)
我希望有人可以通过我在精神解析中使用>和>>操作符的无知来发光.
我有一个工作语法,顶级规则看起来像
test = identifier >> operationRule >> repeat(1,3)[any_string] >> arrow >> any_string >> conditionRule;
Run Code Online (Sandbox Code Playgroud)
它依赖于属性来自动将解析后的值分配给融合自适应结构(即boost元组).
但是,我知道一旦我们匹配operationRule,我们必须继续或失败(即我们不希望允许回溯尝试以其他规则开头identifier).
test = identifier >>
operationRule > repeat(1,3)[any_string] > arrow > any_string > conditionRule;
Run Code Online (Sandbox Code Playgroud)
这会导致一个神秘的编译器错误('boost::Container' : use of class template requires template argument list).Futz一点点以下编译:
test = identifier >>
(operationRule > repeat(1,3)[any_string] > arrow > any_string > conditionRule);
Run Code Online (Sandbox Code Playgroud)
但属性设置不再有效 - 我的数据结构在解析后包含垃圾.这可以通过添加类似的操作来修复[at_c<0>(_val) = _1],但这似乎有点笨拙 - 以及根据boost文档使事情变慢.
所以,我的问题是
()operationRule匹配之后是否真的停止了回溯(我怀疑不是,似乎如果(...)允许整个解析器内部失败回溯)?所以我们有一个简单的分裂:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
vector<string> split(const string& s, const string& delim, const bool keep_empty = true) {
vector<string> result;
if (delim.empty()) {
result.push_back(s);
return result;
}
string::const_iterator substart = s.begin(), subend;
while (true) {
subend = search(substart, s.end(), delim.begin(), delim.end());
string temp(substart, subend);
if (keep_empty || !temp.empty()) {
result.push_back(temp);
}
if (subend == s.end()) {
break;
}
substart = subend + delim.size();
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
当我从C ++(11)中读取文件时,我使用以下命令将它们映射到内存中:
boost::interprocess::file_mapping* fm = new file_mapping(path, boost::interprocess::read_only);
boost::interprocess::mapped_region* region = new mapped_region(*fm, boost::interprocess::read_only);
char* bytes = static_cast<char*>(region->get_address());
Run Code Online (Sandbox Code Playgroud)
当我希望非常快地逐字节读取时,这很好。但是,我创建了一个csv文件,该文件要映射到内存,读取每一行并在逗号上分割每一行。
是否可以通过对上面的代码进行一些修改来做到这一点?
(我正在映射到内存,因为我有很多内存,并且我不希望磁盘/ IO流出现任何瓶颈)。