标签: boost-spirit

Boost.Spirit.Qi:获取规则的属性并将其设置为封闭规则的struct属性的字段?

就像其他许多问题一样,我正在尝试使用Boost.Spirit.Qi将简单语法解析为结构树.

我会尝试提炼我想要做的最简单的案例.我有:

struct Integer {
  int value;
};
BOOST_FUSION_ADAPT_STRUCT(Integer, (int, value))
Run Code Online (Sandbox Code Playgroud)

后来,在语法结构中,我有以下成员变量:

qi::rule<Iterator, Integer> integer;
Run Code Online (Sandbox Code Playgroud)

这是我定义的

integer = qi::int_;
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试实际解析整数时,使用

qi::phrase_parse(iter, end, g, space, myInteger);
Run Code Online (Sandbox Code Playgroud)

myInteger.value在成功解析后始终未初始化.同样,我尝试了以下定义(显然那些不编译的定义是错误的):

integer = qi::int_[qi::_val = qi::_1]; //compiles, uninitialized value
integer = qi::int_[qi::_r1 = qi::_1]; //doesn't compile
integer = qi::int_[phoenix::bind(&Integer::value, qi::_val) = qi::_1]; //doesn't
integer = qi::int_[phoenix::at_c<0>(qi::_val) = qi::_1]; //doesn't
Run Code Online (Sandbox Code Playgroud)

显然,我误解了一些关于精神,凤凰或其他东西的东西.我的理解是,当方括号中的部分作为函数对象执行时,这里qi::_1的第一个属性qi::int_应该表示已解析的整数.我假设函数对象将采用封闭integer属性qi::_val并尝试将解析后的整数分配给它.我的猜测是因为我的BOOST_FUSION_ADAPT_STRUCT调用,两者兼容,从静态分析的角度来看,情况似乎确实如此,但数据并未得到保留.

是否有参考(&)指定我在某处或某处遗漏?

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

7
推荐指数
1
解决办法
3534
查看次数

C++/Boost:编写更强大的sscanf替代品

我想用C++编写一个函数来替换C的sscanf,它将匹配分配给迭代器.

基本上,我想要的东西:

string s = "0.5 6 hello";
std::vector<boost::any> any_vector;
sscanv(s, "%f %i %s", any_vector);
cout << "float: " << any_cast<float>(any_vector[0]);
cout << "integer: " << any_cast<integer(any_vector[1]);
cout << "string: " << any_cast<string>(any_vector[2]);
Run Code Online (Sandbox Code Playgroud)

确切的细节可能会有所不同,但你明白了.任何实施的想法?

到目前为止的选项以及目前的问题:

  • std :: istringstream:没有用于匹配常量表达式的操纵器
  • Boost.Regex:不确定这是否有效,而且看起来要比这更复杂
  • Boost.Spirit:不要认为这适用于动态生成的格式字符串,并且它似乎也更复杂
  • sscanf:它可以工作,但是非标准等,并且使用它会需要很多开销,因为参数的数量是在编译时确定的

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

7
推荐指数
1
解决办法
2677
查看次数

提升精神Qi重新建立跳过自定义跳过语法

到目前为止,我的语法一直使用标准boost::spirit::ascii::space/ boost::spirit::ascii::space_type队长.

我有一些使用船长的规则和一些不使用船长的规则

qi::rule<Iterator, PTR<Expression>(), ascii::space_type> expression;
qi::rule<Iterator, PTR<Term>()> term;
Run Code Online (Sandbox Code Playgroud)

当我在跳过非终结符(例如term)中使用非跳过非终结符(例如expression)时,一切都像我期望的那样工作 - 空格只对term非终结内部很重要.

此外,到目前为止,我一直很好,包括使用不使用qi::skip重新跳过的非终端内的队长的非终结者,例如

index = (qi::lit('[') >> qi::skip(ascii::space)[explist >> qi::lit(']')]);
Run Code Online (Sandbox Code Playgroud)

这样,在[]括号内部的空白并不重要,但在外面.

但是,现在我想添加我自己的自定义队列(我想让换行有意义,然后添加评论跳过).我的船长语法看起来像:

struct skip_grammar : qi::grammar<Iterator> {
  qi::rule<Iterator> start;
  skip_grammar() : skip_grammar::base_type(start) {
    start = qi::char_("\t\r ");
  }
};
Run Code Online (Sandbox Code Playgroud)

我已经能够将它添加到我的规则定义中就好了

qi::rule<Iterator, PTR<Expression>(), skip_grammar> expression;
Run Code Online (Sandbox Code Playgroud)

但我似乎无法弄清楚如何使用我的跳过语法作为参数qi::skip(和替换ascii::space).我尝试使用类型,本地实例变量和全局实例变量.我得到的最远的就是抱怨我的skip_grammar需要一个拷贝构造函数.所以我尝试将一个复制构造函数添加到我的跳过语法中,但显然boost::noncopyable基类是有原因的,因为我的二进制文件几乎立即就被发现了.

我应该如何使用它?

谢谢

c++ boost-spirit boost-spirit-qi

7
推荐指数
1
解决办法
1884
查看次数

Boost Variant:如何建模JSON?

我正在尝试使用Boost Spirit商店JSON对象将JSON字符串解析为递归数据结构:

Value <== [null, bool, long, double, std::string, Array, Object];
Array <== [Value, Value, Value, ...];
Object <== ["name1": Value, "name2": Value, ...];
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

#include <map>
#include <vector>
#include <string>
#include <boost/variant.hpp>
#include <boost/shared_array.hpp>
#include <boost/shared_ptr.hpp>

struct JsonNull {};
struct JsonValue;

typedef std::map<std::string, JsonValue *> JsonObject;
typedef std::vector<JsonValue *> JsonArray;

struct JsonValue : boost::variant<JsonNull, bool, long, double, std::string, JsonArray, JsonObject>
{
};

JsonValue aval = JsonObject();
Run Code Online (Sandbox Code Playgroud)

编译时我得到错误:

Error C2440: 'initializing' : cannot convert from 'std::map<_Kty,_Ty>' to 'JsonValue'
Run Code Online (Sandbox Code Playgroud)

而且,如何安全地将JsonValue转换为JsonObject?当我尝试做:

boost::get<JsonObject>(aval) …
Run Code Online (Sandbox Code Playgroud)

c++ json boost boost-spirit boost-variant

7
推荐指数
1
解决办法
2243
查看次数

如何使用boost :: spirit将一系列单词解析为一个向量?

我正在努力学习boost::spirit.作为一个例子,我试图将一系列单词解析成一个单词vector<string>.我试过这个:

#include <boost/spirit/include/qi.hpp>
#include <boost/foreach.hpp>

namespace qi = boost::spirit::qi;

int main() {

  std::vector<std::string> words;
  std::string input = "this is a test";

  bool result = qi::phrase_parse(
      input.begin(), input.end(),
      +(+qi::char_),
      qi::space,
      words);

  BOOST_FOREACH(std::string str, words) {
    std::cout << "'" << str << "'" << std::endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

这给了我这个输出:

'thisisatest'
Run Code Online (Sandbox Code Playgroud)

但我想要以下输出,其中每个单词分别匹配:

'this'
'is'
'a'
'test'
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我想避免qi::grammar为这个简单的情况定义我自己的子类.

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

7
推荐指数
1
解决办法
3527
查看次数

使用Boost.Spirit在C++中解析SQL查询

我创建了一个数据库引擎,我可以在其中创建和修改表,并将它们添加到数据库中.为了解析SQL查询,我使用EBNF表单实现了Boost.Spirit库.我正确设置了解析器,并成功解析了每个规则.

我的问题是我现在不知道如何整合这两者.Boost.Spirit解析器只验证输入是否正确,但我需要它来实际执行某些操作.我查找了语义操作,但它们似乎没有处理我正在寻找的内容.

例如,如果我有一个查询,例如:
new_table <- SELECT (id < 5) old_table;

我希望它使用规则验证输入,然后调用函数
Table Database::Select(Table t , Condition c){ ... }
并将标记作为参数传递.

我如何整合解析器?

c++ sql parsing boost-spirit

7
推荐指数
1
解决办法
4267
查看次数

是否有任何明确的入门级文档可用于boost-spirit?

我试图浏览Boost Spirit页面上的官方文档,但我发现它完全无法理解(尽管有超过25年的编程经验和英语语言学位) - 它显然是由一个对系统了解得很好的人(好)但假设读者也很了解系统(坏).我需要一些不会像这样的句子

精神中的解析器和发电机完全归功于它

显然是"归属"的含义,我不知道,网络搜索没有帮助.要么

序列需要属性类型来公开融合序列的概念,其中该融合序列的所有元素必须与组件序列的相应元素兼容

什么是融合序列?我所知道的唯一一个发生在太阳下.如何在C++中"揭露"一个"概念"?

从初学者的角度来看,是否有任何好的教程描述了Boost Spirit?

c++ documentation boost-spirit

7
推荐指数
1
解决办法
345
查看次数

提升精神QI慢

我尝试使用Boost Spirit QI解析TPCH文件.我的实现灵感来自Spirit QI的员工示例(http://www.boost.org/doc/libs/1_52_0/libs/spirit/example/qi/employee.cpp).数据采用csv格式,令牌以"|"分隔.字符.

它工作但很慢(1秒时为20秒).

这是我对lineitem文件的qi语法:

struct lineitem {
    int l_orderkey;
    int l_partkey;
    int l_suppkey;
    int l_linenumber;
    std::string l_quantity;
    std::string l_extendedprice;
    std::string l_discount;
    std::string l_tax;
    std::string l_returnflag;
    std::string l_linestatus;
    std::string l_shipdate;
    std::string l_commitdate;
    std::string l_recepitdate;
    std::string l_shipinstruct;
    std::string l_shipmode;
    std::string l_comment;
};

BOOST_FUSION_ADAPT_STRUCT( lineitem,
    (int, l_orderkey)
    (int, l_partkey)
    (int, l_suppkey)
    (int, l_linenumber)
    (std::string, l_quantity)
    (std::string, l_extendedprice)
    (std::string, l_discount)
    (std::string, l_tax)
    (std::string, l_returnflag)
    (std::string, l_linestatus)
    (std::string, l_shipdate)
    (std::string, l_commitdate)
    (std::string, l_recepitdate)
    (std::string, l_shipinstruct)
    (std::string, l_shipmode)
    (std::string, l_comment)) 

vector<lineitem>* lineitems=new …
Run Code Online (Sandbox Code Playgroud)

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

7
推荐指数
1
解决办法
2181
查看次数

如何使用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
查看次数

将包含字符串成员的类调整为合成属性

我正在尝试将字符串解析为symbol包含std::string成员的自定义类型的属性.我以为我可以BOOST_FUSION_ADAPT_STRUCT在这里使用,但这不起作用.

如果我宣布规则是rule<It, std::string(), space_type>有效的.如果我将其定义为rule<It, symbol(), space_type>失败,并显示错误"no type name value_typein symbol".我认为Spirit正在尝试将值字符附加到属性中,该属性会按预期失败.但是,如果没有添加额外的中间规则来捕获std::string属性,是不是有办法使这项工作成功?

这是完整的MWE:

#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>

struct symbol 
{ 
    std::string repr; 
};

BOOST_FUSION_ADAPT_STRUCT(symbol, (std::string, repr))

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct test_grammar : qi::grammar<Iterator, symbol(), qi::ascii::space_type> {
    test_grammar() : test_grammar::base_type{start} {
        start = qi::lexeme[+qi::char_("a-z")];
    }

    qi::rule<Iterator, symbol(), qi::ascii::space_type> start;
};

#include <iostream>

auto main() -> int {
    test_grammar<std::string::iterator> grammar{};
    auto input …
Run Code Online (Sandbox Code Playgroud)

c++ boost-spirit boost-fusion

7
推荐指数
1
解决办法
369
查看次数