在Boost Spirit语法中获取当前行 [英] Get current line in boost spirit grammar

查看:54
本文介绍了在Boost Spirit语法中获取当前行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用boost spirit来获取要解析的文件的当前行.我创建了一个语法类和我的结构来解析我的命令.我还想跟踪找到命令的那一行,并将其解析到我的结构中.我将istream文件迭代器包装在multi_pass迭代器中,然后将其包装在boost :: spirit :: classic :: position_iterator2中.在我的语法规则中,如何获得迭代器的当前位置?或者这不可能吗?

I am trying to get the current line of the file I am parsing using boost spirit. I created a grammar class and my structures to parse my commands into. I would also like to keep track of which line the command was found on and parse that into my structures as well. I have wrapped my istream file iterator in a multi_pass iterator and then wrapped that in a boost::spirit::classic::position_iterator2. In my rules of my grammar how would I get the current position of the iterator or is this not possible?

更新:这类似于该问题,但我只需要能够对所有已处理的行进行计数即可.我不需要执行解决方案中完成的所有额外缓冲.

Update: It is similar to that problem but I just need to be able to keep a count of all the lines processed. I don't need to do all of the extra buffering that was done in the solution.

推荐答案

更新:这类似于该问题,但我只需要能够对所有已处理的行进行计数即可.我不需要执行解决方案中完成的所有额外缓冲.

Update: It is similar to that problem but I just need to be able to keep a count of all the lines processed. I don't need to do all of the extra buffering that was done in the solution.

保留所有已处理行的计数与获取当前行"几乎不一样.

Keeping a count of all lines processed is not nearly the same as "getting the current line".

如果这是您需要的,只需在解析后检查一下即可:

If this is what you need, just check it after the parse:

在魔盒上直播 >

Live On Wandbox

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_line_pos_iterator.hpp>
#include <fstream>
#include <set>
namespace qi = boost::spirit::qi;

int main() {
    using It = boost::spirit::istream_iterator;

    std::ifstream ifs("main.cpp");
    boost::spirit::line_pos_iterator<It> f(It(ifs >> std::noskipws)), l;

    std::set<std::string> words;
    if (qi::phrase_parse(f, l, *qi::lexeme[+qi::graph], qi::space, words)) {
        std::cout << "Parsed " << words.size() << " words";
        if (!words.empty())
            std::cout << " (from '" << *words.begin() << "' to '" << *words.rbegin() << "')";
        std::cout << "\nLast line processed: " << boost::spirit::get_line(f) << "\n";
    }
}

打印

Parsed 50 words (from '"' to '}')
Last line processed: 22

稍微复杂一点

如果您说不,等等,我真的 did 想获得当前行/parsing/".真正的全数在这里:

Slightly More Complex Take

If you say "no, wait, I really did want to get the current line /while parsing/". The real full monty is here:

以下是使用 iter_pos 的完全精简版本:

Here's the completely trimmed down version using iter_pos:

在魔盒上直播 >

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/support_line_pos_iterator.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <fstream>
#include <map>

namespace qi = boost::spirit::qi;
namespace qr = boost::spirit::repository::qi;

using LineNum = size_t;

struct line_number_f {
    template <typename It> LineNum operator()(It it) const { return get_line(it); }
};

static boost::phoenix::function<line_number_f> line_number_;

int main() {
    using Underlying = boost::spirit::istream_iterator;
    using It = boost::spirit::line_pos_iterator<Underlying>;
    qi::rule<It, LineNum()> line_no = qr::iter_pos [ qi::_val = line_number_(qi::_1) ];

    std::ifstream ifs("main.cpp");
    It f(Underlying{ifs >> std::noskipws}), l;

    std::multimap<LineNum, std::string> words;

    if (qi::phrase_parse(f, l, +(line_no >> qi::lexeme[+qi::graph]), qi::space, words)) {
        std::cout << "Parsed " << words.size() << " words.\n";

        if (!words.empty()) {
            auto& first = *words.begin();
            std::cout << "First word: '" << first.second << "' (in line " << first.first << ")\n";
            auto& last = *words.rbegin();
            std::cout << "Last word: '" << last.second << "' (in line " << last.first << ")\n";
        }

        std::cout << "Line 20 contains:\n";
        auto p = words.equal_range(20);
        for (auto it = p.first; it != p.second; ++it)
            std::cout << " - '" << it->second << "'\n";

    }
}

打印:

Parsed 166 words.
First word: '#include' (in line 1)
Last word: '}' (in line 46)
Line 20 contains:
 - 'int'
 - 'main()'
 - '{'

这篇关于在Boost Spirit语法中获取当前行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆