Boost Spirit(经典):内联解析器,除跳过注释外工作

时间:2014-09-12 13:12:50

标签: c++ boost boost-spirit

编辑:正如关于sehe的回答的评论中提到的那样,下面的代码看起来很好;这是我处理迭代器(这里没有显示)的错误。对不起这是我的错。投票结束非主题/不可复制。

EDIT2:详细说明...... 如果您正在使用boost::spirit::istream_iteratorifstream提供给解析功能(就像我一样)不要忘记先在unsetf( std::ios::skipws )上调用ifstream,否则你的解析会失败......


我有一个DSL(特定于域的语言)文件,看起来像这样:

# Comment (optional)

codepage = "ISO-8859-2";
...

即,codepage规范是文件中的第一个非注释语句,或者该文件被认为是默认代码页。

我为这项任务征服了Boost Spirit。由于技术原因(咳嗽 AIX / XLC 咳嗽),我不得不继续使用Spirit Classic,并且在经历了一些令人头疼的教程之后 - 总是瞄准更多的参与设置,比我想要的要复杂得多 - 我想出了这段代码:

#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_rule.hpp>
#include <boost/spirit/include/classic_utility.hpp>

#include <string>

namespace spirit_classic = boost::spirit::classic;

template< typename Iterator >
static std::string getCodepage( Iterator first, Iterator last )
{
    std::string codepage;

    spirit_classic::parse(
        first,
        last,
        spirit_classic::as_lower_d[ "codepage" ]
            >> spirit_classic::ch_p( '=' )
            >> spirit_classic::lexeme_d[ spirit_classic::ch_p( '"' )
                >> ( +( spirit_classic::anychar_p - spirit_classic::ch_p( '"' ) ) )[spirit_classic::assign_a( codepage )]
                >> spirit_classic::ch_p( '"' ) ]
        >> spirit_classic::ch_p( ';' ),
        spirit_classic::space_p | spirit_classic::comment_p( '#' )
        );

    if ( codepage.empty() )
    {
        codepage = "UTF-8";
    }

    return codepage;
}

这很有效......除了船长:

...
spirit_classic::space_p | spirit_classic::comment_p( '#' )
...

这可以跳过空白 - 但完全没有跳过评论(即从'#'到行尾的任何内容),我理解`comment_p(&#39;#&#39;)来实现

显然我明白了一些错误。我只是无法弄清楚是什么。帮助

1 个答案:

答案 0 :(得分:1)

我在这里没有太多的见解,我只是在这里测试MSVC / GCC,但问题可能是comment_p试图消耗eolspace_p吃掉了{ {1}}船长代替)?

所以要么你可以使用spirit_classic::blank_p(并明确你的eols),你可能有幸逆转了船长的分支:

    spirit_classic::comment_p( '#' ) | spirit_classic::space_p

查看 Live On Coliru

#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_rule.hpp>
#include <boost/spirit/include/classic_utility.hpp>

#include <string>

namespace spirit_classic = boost::spirit::classic;

template< typename Iterator >
static std::string getCodepage( Iterator first, Iterator last )
{
    std::string codepage;

    spirit_classic::parse(
        first,
        last,
        spirit_classic::as_lower_d[ "codepage" ]
            >> spirit_classic::ch_p( '=' )
            >> spirit_classic::lexeme_d[ spirit_classic::ch_p( '"' )
                >> ( +( spirit_classic::anychar_p - spirit_classic::ch_p( '"' ) ) )[spirit_classic::assign_a( codepage )]
                >> spirit_classic::ch_p( '"' ) ]
        >> spirit_classic::ch_p( ';' ),
         spirit_classic::comment_p( '#' ) | spirit_classic::space_p
        );

    if ( codepage.empty() )
    {
        codepage = "UTF-8";
    }

    return codepage;
}

int main()
{
    std::string input = "# Comment (optional)\n"
        "\n"
        "\n"
        "\n"
        "codepage = \"ISO-8859-2\"; \n";

    std::cout << getCodepage(input.begin(), input.end());
}

打印

ISO-8859-2