我一直在尝试为 callgrind 工具的输出创建一个 Boost.Spirit 解析器,它是 valgrind 的一部分。Callgrind 输出一种特定于领域的嵌入式编程语言 (DSEL),它可以让你做各种很酷的事情,比如合成计数器的自定义表达式,但它不容易解析。
我在https://gist.github.com/ned14/5452719#file-sample-callgrind-output放置了一些示例 callgrind 输出。我已经在https://gist.github.com/ned14/5452719#file-callgrindparser-hpp和https://gist.github.com/ned14/5452719对 Boost.Spirit 词法分析器和解析器进行了目前的最佳尝试#file-callgrindparser-cxx。Lexer 部分很简单:它将标记值、非空白文本、注释、行尾、整数、十六进制、浮点数和运算符(忽略示例代码中的标点符号,它们未使用)。空白被跳过。
到目前为止,一切都很好。问题是解析标记化的输入流。我什至还没有尝试过主要的节,我仍在尝试解析可能出现在文件中任何位置的标记值。标签值如下所示:
tagtext: unknown series of tokens<eol>
它可以是自由格式的文本,例如
desc: I1 cache: 32768 B, 64 B, 8-way associative, 157 picosec hit latency
在这种情况下,您希望将标记集转换为字符串,即转换为 iterator_range 并提取。
然而,它可能是一个表达式,例如
event: EPpsec = 316 Ir + 1120 I1mr + 1120 D1mr + 1120 D1mw + 1362 ILmr + 1362 DLmr + 1362 DLmw
这表示从现在开始,事件 EPpsec 将被合成为 Ir 乘以 316 添加到 I1mr 乘以 1120 添加到 ... 等等。
我想在这里说明的一点是,标签-值对需要作为任意标记集进行累积,并后处理为我们以后将它们变成的任何内容。
为此,Boost.Spirit 的 utree() 类看起来正是我想要的,这就是示例代码所使用的。但是在 VS2012 上使用带有可变参数模板的 11 月 CTP 编译器,我目前看到这个编译错误:
1>C:\Users\ndouglas.RIMNET\documents\visual studio 2012\Projects\CallgrindParser\boost\boost/range/iterator_range_core.hpp(56): error C2440: 'static_cast' : cannot convert from 'boost::spirit::detail::list::node_iterator<const boost::spirit::utree>' to 'base_iterator_type'
1> No constructor could take the source type, or constructor overload resolution was ambiguous
1> C:\Users\ndouglas.RIMNET\documents\visual studio 2012\Projects\CallgrindParser\boost\boost/range/iterator_range_core.hpp(186) : see reference to function template instantiation 'IteratorT boost::iterator_range_detail::iterator_range_impl<IteratorT>::adl_begin<const Range>(ForwardRange &)' being compiled
1> with
1> [
1> IteratorT=base_iterator_type
1> , Range=boost::spirit::utree
1> , ForwardRange=boost::spirit::utree
1> ]
...这表明我的 base_iterator_type 是 Boost.Spirit multi_pass<> 包装的 istreambuf_iterator 用于前向迭代器性质,Boost.Spirit 的 utree() 实现不知何故无法理解。问题是,我不确定这是我的错误代码还是错误的 Boost.Spirit 代码,因为 line_pos_iterator<> 未能正确指定其 forward_iterator 概念标签。
感谢过去的 Stackoverflow 帮助,我可以编写一个纯非标记化的语法,但它会很脆弱。正确的解决方案是标记化并使用能够相当任意输入的自由格式语法。让 Boost.Spirit 的 Lex 和 Grammar 在现实世界的示例而不是玩具示例中协同工作的示例数量非常少。因此,任何帮助将不胜感激。
尼尔