可以使用Spirit(Boost C++库的一部分)来解析来自流的二进制数据吗?例如,它可以用于将来自套接字的数据解析为结构,字节和单个位标志吗?谢谢!
我使用spirit mini_c样本进行了一些测试.不幸的是,它没有像预期的那样保持运算符的优先级:
int main()
{
return 3 > 10 || 3 > 1;
}
Run Code Online (Sandbox Code Playgroud)
评估为0.
return (3 > 10) || (3 > 1);
Run Code Online (Sandbox Code Playgroud)
返回1
我试图移动"||"的定义 和"&&"到构造函数的顶部
template <typename Iterator>
expression<Iterator>::expression(
Run Code Online (Sandbox Code Playgroud)
但这并没有改变任何事情.如何解决这个问题.我正在使用boost 1.3.38.
我对提升::精神深感钦佩,不理解它永远的挫折;)
我有太贪婪的字符串的问题,因此它不匹配.下面是一个不解析的最小示例,因为txt规则会结束.
关于我想做什么的更多信息:目标是解析一些伪SQL并跳过空格.在一个声明中
select foo.id, bar.id from foo, baz
Run Code Online (Sandbox Code Playgroud)
我需要将其from视为特殊关键字.规则是这样的
"select" >> txt % ',' >> "from" >> txt % ','
Run Code Online (Sandbox Code Playgroud)
但它显然不起作用 bar.id from foo看作一个项目.
#include <boost/spirit/include/qi.hpp>
#include <iostream>
namespace qi = boost::spirit::qi;
int main(int, char**) {
auto txt = +(qi::char_("a-zA-Z_"));
auto rule = qi::lit("Hello") >> txt % ',' >> "end";
std::string str = "HelloFoo,Moo,Bazend";
std::string::iterator begin = str.begin();
if (qi::parse(begin, str.end(), rule))
std::cout << "Match !" << std::endl;
else
std::cout << "No match :'(" << std::endl; …Run Code Online (Sandbox Code Playgroud) 我正在尝试用boost :: spirit库编写一个python解析器.这是代码:
template <typename Iterator>
class Parser : public qi::grammar<Iterator, space_type>
{
public:
Parser() : Parser::base_type(small_stmt)
{
NEWLINE = lit("<NEWLINE>");
INDENT = lit("<INDENT>");
DEDENT = lit("<DEDENT>");
ENDMARKER = lit("<EOT>");
NAME = identifier.alias();
NUMBER = integer|longinteger|floatnumber|imagnumber;
STRING = stringliteral.alias();
identifier = (alpha | '_') >> *(alpha | digit | '_');
stringliteral = -stringprefix >> (shortstring | longstring);
stringprefix = lit("r") | lit("u") | lit("ur") | lit("R") | lit("U") | lit("UR") | lit("Ur") | lit("uR") | lit("b") | lit("B") | lit("br") …Run Code Online (Sandbox Code Playgroud) 在我阅读了关于boost :: spirit的教程之后,由于解析器组合器语法,我非常喜欢它.制作解析器非常简单.
遗憾的是,在从解析器中获取复杂数据结构的问题上,教程并不那么精确.我正试图进入Kaleidoscope AST.
无论如何,这是我的AST代码:
#ifndef __AST_HPP__
#define __AST_HPP__
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <string>
#include <vector>
namespace ast {
struct add;
struct sub;
struct mul;
struct div;
struct func_call;
template<typename OpTag> struct binary_op;
typedef boost::variant<double, std::string, boost::recursive_wrapper<binary_op<
add>>, boost::recursive_wrapper<binary_op<sub>>,
boost::recursive_wrapper<binary_op<mul>>, boost::recursive_wrapper<
binary_op<div>>, boost::recursive_wrapper<func_call>>
expression;
template<typename OpTag>
struct binary_op {
expression left;
expression right;
binary_op(const expression & lhs, const expression & rhs) :
left(lhs), right(rhs) {
}
};
struct …Run Code Online (Sandbox Code Playgroud) 我已经成功地使用boost::spirit::qi到解析由内置的解析器(如流byte_,little_word等).但是,我现在需要解析不完全属于这些类别之一的数据.例如,我想将16.16定点二进制数转换为double; 例如,little_word << little_16p16将解析a uint16_t后跟a double(从定点数解析).
我首先考虑语义动作,但(我认为......)它们不合适,因为它们不会更改与解析器关联的属性的类型.我也无法弄清楚如何使员工struct-parsing示例适应这种情况,因为它依赖于提供的隐式转换boost::fusion.这种方法在这里不起作用,因为我显然不能uint32_t在double不引起重大问题的情况下定义隐式转换.
我倾向于我需要添加非终端来包装内置的二进制原语解析器或从头开始编写终端解析器.即使看了之后qi_binary.hpp,我也不知道该如何做.任何人都可以提供一些示例代码和/或指导我开始相关的参考资料吗?
我正在尝试使用提升精神构建一个AST,并且当使用C++ 11 lambda表达式作为语义动作时,我一直在努力构建合成参数.
说我有一条规则:
qi::rule<char*,ascii::space_type,SomeStruct()> rule = some_parser[[](some_type val){/*code to build SomeStruct from val*/}];
我的lambda如何返回合成参数(SomeStruct)?按返回值?因为qi :: _ val在这种情况下不可用吗?(这对我来说有点模糊,如果这个问题没有很好地表达,那就很抱歉)
提前感谢任何正确方向的指针!
我正试图抓住新的Spirit X3(升级1.61.0).
我的机器是运行Linux的MacBook Pro(i7-4750HQ).
使用Spirit的第2版我习惯了很长的编译时间,但这感觉不对.对于表达式解析器的以下第一步,编译需要20秒.
我以为X3会更快,这个合理吗?我的代码不是最理想的吗?
编译器设置(铿锵3.8.0)
clang++ -c -pipe -std=c++14 -ftemplate-depth=512 -g -w -Wall -Wno-unused-parameter -fPIC
Run Code Online (Sandbox Code Playgroud)
码:
//#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <string>
#include <vector>
//--------------------------------------------------------------------------------------------------
namespace client { namespace ast
{
namespace fusion = boost::fusion;
namespace x3 = boost::spirit::x3;
struct number : x3::variant<int, double> {
using base_type::base_type;
using base_type::operator=;
};
struct add_ast;
struct mult_ast;
struct block_ast;
struct function;
struct expr_ast : x3::variant<
number,
x3::forward_ast<function>,
x3::forward_ast<add_ast>,
x3::forward_ast<mult_ast>,
x3::forward_ast<block_ast>
> {
using base_type::base_type;
using …Run Code Online (Sandbox Code Playgroud) 此代码不编译(gcc 5.3.1 + boost 1.60):
#include <boost/spirit/home/x3.hpp>
namespace x3 = boost::spirit::x3;
template <typename T>
void parse(T begin, T end) {
auto dest = x3::lit('[') >> x3::int_ >> ';' >> x3::int_ >> ']';
auto on_portal = [&](auto& ctx) {};
auto portal = (x3::char_('P') >> -dest)[on_portal];
auto tiles = +portal;
x3::phrase_parse(begin, end, tiles, x3::eol);
}
int main() {
std::string x;
parse(x.begin(), x.end());
}
Run Code Online (Sandbox Code Playgroud)
它失败并带有静态断言:
error: static assertion failed: Attribute does not have the expected size.
Run Code Online (Sandbox Code Playgroud)
感谢wandbox我也尝试了boost 1.61和clang,两者都产生了相同的结果.
如果我删除附加的语义动作portal,它编译得很好; 如果我dest …
我试图浏览Boost Spirit页面上的官方文档,但我发现它完全无法理解(尽管有超过25年的编程经验和英语语言学位) - 它显然是由一个对系统了解得很好的人(好)但假设读者也很了解系统(坏).我需要一些不会像这样的句子
精神中的解析器和发电机完全归功于它
显然是"归属"的含义,我不知道,网络搜索没有帮助.要么
序列需要属性类型来公开融合序列的概念,其中该融合序列的所有元素必须与组件序列的相应元素兼容
什么是融合序列?我所知道的唯一一个发生在太阳下.如何在C++中"揭露"一个"概念"?
从初学者的角度来看,是否有任何好的教程描述了Boost Spirit?