相关疑难解决方法(0)

如何使用boost :: spirit解析csv

我有这个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)

c++ csv boost boost-spirit boost-spirit-qi

7
推荐指数
2
解决办法
9624
查看次数

提升精神将整个比赛作为一个字符串

我正在尝试使用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*与大小?

c++ boost boost-spirit boost-spirit-qi

6
推荐指数
1
解决办法
2096
查看次数

boost::spirit 带参数的惰性解析器?

除了不祥的暗示之外,我找不到任何关于这方面的信息,这可能是完全不可能的,但我不想简单地相信它,因为在这种情况下,惰性解析器似乎毫无用处。我想要做的是在解析时根据之前的一些非终端的结果选择一个解析器。它本质上可以归结为:

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,请告诉我;-)

c++ parsing boost-spirit

5
推荐指数
1
解决办法
333
查看次数

boost :: spirit :: qi Expectation Parser和parser对意外行为进行分组

我希望有人可以通过我在精神解析中使用>>>操作符的无知来发光.

我有一个工作语法,顶级规则看起来像

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文档使事情变慢.

所以,我的问题是

  1. 是否值得阻止反向追踪?
  2. 为什么我需要分组运算符 ()
  3. 我的上一个例子在operationRule匹配之后是否真的停止了回溯(我怀疑不是,似乎如果(...)允许整个解析器内部失败回溯)?
  4. 如果上一个问题的答案是/ …

c++ parsing boost boost-spirit boost-spirit-qi

4
推荐指数
1
解决办法
1197
查看次数

如何使我的分割只在一个实线上工作,并能够跳过字符串的引用部分?

所以我们有一个简单的分裂:

#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++ string parsing boost split

3
推荐指数
1
解决办法
1925
查看次数

读取映射到内存的CSV文件的最简单方法?

当我从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流出现任何瓶颈)。

c++ csv io boost memory-mapped-files

3
推荐指数
1
解决办法
1914
查看次数