问题标签 [boost-spirit]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
342 浏览

c++ - boost::spirit stream_parser 消耗太多?

我在将具有 iostream 解析支持的类集成到精神解析器中时遇到了一些麻烦。下面的示例(根据 Spirit 示例修改)演示了该问题。如果我尝试仅解析自定义类,它会成功,如第一次解析和调用断言所示。如果我尝试解析自定义类以及(在这种情况下)逗号和浮点数,解析器将失败。

谁能阐明为什么会这样?如果我使用精神解析器而不是流解析器,我可以使第二个示例工作,但这违背了使用 stream_parser 的目的。

我在本地示例中启用了规则调试,这表明自定义解析器使用了字符串的全部内容 - 但是,代码显示它不应该这样做......

任何帮助表示赞赏!

提升 1.44.0,gcc 4.1.1

0 投票
1 回答
1419 浏览

c++ - boost::spirit 示例无法编译

我正在关注 Spirit 文档中的教程,但我被困在这里:

当我编译它时,它显示了这个错误:

怎么了?

0 投票
1 回答
2103 浏览

c++ - boost::bind 和 boost::phoenix 占位符之间的混淆

boost::spirit文档有这个重要的警告

为 Spirit.Qi 编写语义动作有多种方式:使用普通函数、Boost.BindBoost.LambdaPhoenix。后三个允许您使用特殊的占位符来控制参数的放置(_1_2等)。这些库中的每一个都有自己的占位符实现,都在不同的命名空间中。您必须确保不要将占位符与它们不属于的库混合使用,并且在编写语义操作时不要使用不同的库。

通常,for Boost.Bind、use ::_1::_2等(是的,这些占位符是在全局命名空间中定义的)。

用于Boost.Lambda使用命名空间中定义的占位符boost::lambda

对于使用 Phoenix 编写的语义操作,请使用命名空间中定义的占位符boost::spirit。请注意,为了您的方便,所有现有的占位符也可以从命名空间获得boost::spirit::qi

文档

好的,所以我写了这段代码

请注意使用::_1

但是,我仍然收到此编译器错误

如何修复此编译器错误?

0 投票
1 回答
428 浏览

c++ - 令牌解析器语义动作

我已经根据Spirit lex 示例 4中显示的代码编写了一个工作令牌解析器

我的一条规则看起来像这样

这很好用。当出现

它按我的预期输出

将名称语句设置为:xyz

现在我想做一些有用的事情,将找到的名称存储到一个类中。从解析器语义示例工作,我编写了这段代码

这不编译

为什么编译器抱怨试图从 bool 转换为 string?我看不到布尔值。

0 投票
1 回答
569 浏览

c++ - 在语义操作中发现错误时停止解析器

当语义操作代码发现问题时,我希望停止令牌解析器。

如果 x > 10

在语法上是正确的,但如果 x 不存在,解析器应该停止

语法规则和语义动作是这样的

所以现在我添加一个检查标识符是否存在

这行得通!

我对优雅并不感到兴奋。语法语法现在很难阅读,并且混合使用 boost::bind 和 boost::phoenix::bind 非常令人困惑。

我该如何改进它?我想从 phoenix::bind 获取 'hit' 参数,以便我可以在 cRuleKit::AddCondition() 中进行检查,从而保持语法和操作分开并避免使用 boost::bind。


答案是使用占位符 _pass

0 投票
2 回答
3782 浏览

c++ - 最小化 boost::spirit 编译时间

减少 boost::spirit 编译时间的任何想法?

我刚刚移植了一个 flex 解析器来 boost::spirit。EBNF 有大约 25 条规则。

结果运行良好,运行时性能良好。

问题是编译需要永远!这大约需要十分钟,并且需要近千兆字节的内存。最初的 flex 解析器在几秒钟内编译完毕。

我正在使用 boost 版本 1.44.0 和 Visual Studio 2008。


在 Joel de Guzman 的文章“最佳实践”中,它说

具有复杂定义的规则严重损害了编译器。我们已经看到了超过 100 行长并且需要几分钟才能编译的规则

好吧,我没有那么长的东西,但是我的编译仍然需要几分钟以上

这是我语法中最复杂的部分。它是否适合在某种程度上被分解成更小的部分?


通过注释掉部分语法,我发现了编译器花费最多时间的部分。

我不会称它为复杂,但它肯定是最长的规则。所以我想我会尝试将其拆分,如下所示:

这从总编译时间中节省了几分钟!!!

奇怪的是,峰值内存需求保持不变,只是需要更少的时间

所以,我觉得我在学习 boost::spirit 方面的所有努力都将是值得的。

我确实认为编译器需要以这种方式进行如此仔细的引导有点奇怪。我原以为现代编译器会注意到该规则只是独立 OR 规则的列表。


我花了 7 天的大部分时间学习 boost::spirit 并从 flex 移植一个小而真实的解析器。我的结论是它可以工作并且代码非常优雅。不幸的是,简单地为实际应用程序扩展教程示例代码的天真使用很快就会使编译器负担过重——编译所花费的内存和时间变得完全不切实际。显然有一些技术可以解决这个问题,但它们需要我没有时间学习的神秘知识。我想我会坚持使用 flex ,这可能是丑陋和过时的,但相对简单且闪电般快速。

0 投票
2 回答
361 浏览

c++ - boost-spirit 数字解析器并获得所需的合成属性

--edit -- 解决了这个问题:对最后一个旁注的评论会很有帮助。对 phoenix::bind 重载处理的评论也会有所帮助(在我的回答中)。

我正在开发一个具有严格类型要求的系统,我想确保我正在解析满足 int32_t 和 int64_t 约束的整数,我不希望解析器合成并将解析的字符串限制为提到的类型。

我该怎么做?该文档提到long_long仅在支持 64 位的平台上可用,但我也需要在 32 位平台上解析 int64_t。

我的解析器摘录如下:

AddEntry 有一个int32_t重载和一个int64_t重载,是phoenix::static_cast_ on _1order 吗?如果是这种情况,我如何在现代 32 位平台上解析 64 位整数?我假设仅在8008BOOST_HAS_LONG_LONG等过时的硬件上未定义;)。

<Rant> 我希望他们坚持 c99 中规定的标准,并且<boost/cstdint.hpp>我们大多数人都希望针对干净的抽象进行编程。以它们的方式定义数字解析器可能有充分的理由。但是,可以在文档中更好地定义宏计划的使用。 </Rant>

附带说明:上面的条件 epsilon 样式是否在性能上与 case 语句相媲美?

0 投票
2 回答
360 浏览

c++ - 提振精神的建议

我想知道Boost Spirit Library 有多好。

我已经开始阅读文档了,但是它似乎是一个非常庞大的框架,并且要求很多时间成为大师。我真的不想把时间浪费在一个没有想象中那么美妙的框架上。

我想从非常了解这个框架的用户那里得到一些意见。

0 投票
1 回答
2334 浏览

c++ - 如何使用 boost.Spirit 解析带有嵌套括号的表达式?

我需要解析包含键/值对和键/子表达式对的 1 行表达式,例如:

为了使解析器更简单,我愿意分几个步骤进行解析,将第一级标签(这里是 123、456、789、111 和 666)分开,然后在另一个步骤中解析它们的内容。这里 789 的值是"a b c", 111 的值为(1=a 2=b 3=c) (1=x 2=y 3=z) (123=(x y z)).

但是语法在这一点上打败了我,所以我可以找到一种方法来获取匹配括号之间的表达式。我得到的 111 是(1=a 2=b 3=c,它以第一个右括号结束。

我找到了这个方便的示例并尝试使用它,但没有成功:

我怎么能做到这一点?

编辑:我在http://boost-spirit.com/home/articles/qi-example/parsing-a-list-of-key-value-pairs-using-spirit-qi/找到了这个例子

0 投票
1 回答
723 浏览

c++ - 与自动发电机相关的 Boost-spirit-karma 和 boost-variant “概念”

我需要std::vector<boost::variant<..>>用其他对象提供的装饰反序列化 a 。

“装饰”启用的一件事是向量中的一个空条目。我在实际实施中遇到了障碍。但是,我设法将其收缩包装。编译的代码:

有问题的更改试图实现“未定义”类型以及所需的概念。

如果我注释掉这karma::generate一步,std::cout是一个有效的表达式(Boost::variant OutputStreamable)。Spirit 要求为生成器提供OutputStreamable(spirit::karma OutputStreamable) 类型,并且上面的变体应该是OutputStreamable,因为我已将该undefined类型OutputStreamable设置为无操作。

是什么赋予了 ?:(

当使用具有> 2级模板间接的库时,我真的开始质疑 C++ 模板机制是否值得。也许我应该回到直接-c。

编辑1:

好的,Clang 给了我一个合理的first错误......

error: no type named 'properties' in 'boost::spirit::karma::no_auto_mapping_exists'

现在我必须弄清楚如何将 undefined 映射为无操作以获得干净的转换。这个精神文档条目(特别是这个)描述了我需要研究的内容。是否存在由 Spirit 提供的通用未定义类型或在 boost 中定义的类型,该 Spirit 已经映射为 no-op ?

编辑2:

std::vector<boost::optional<boost::variant<..>>>开始看起来很有吸引力,因为精神为他们提供了类型推断。