簡體   English   中英

boost :: spirit :: qi :: parse語法未按預期工作

[英]boost::spirit::qi::parse grammar not working as expected

我嘗試編寫一種語法來解析以下語法:

// - command
// - command value0 ... valueN
// - command -arg0 ... -argN
// - command -arg0 value0 ... valueN ... -argN value0 ... valueN
  • 每個元素應解釋為字符串
  • 字符串中允許使用所有符號
  • 在命令,參數和值之間應允許多個空格
  • 參數始終以“-”開頭
  • 結果應存儲在以下結構中:

     struct Data { std::string m_command; std::map< std::string, std::vector< std::string > m_arg; } 
    • m_command應存儲已解析的命令
    • m_arg應將解析后的參數和相應的值存儲在向量中

我在這里的一個簡短示例中添加了我當前的語法

我的問題:

該向量包含比可用值更多的條目,因為空白也被解釋為值

目前尚不清楚您希望語法器如何工作¹,但從目標數據結構中我得到的印象是,可以通過以下方式大大簡化事情

  1. 使用船長(有關背景,請參見Boost Spirit船長問題
  2. 使用自動屬性傳播而不是鳳凰(另請參閱Boost Spirit:“語義行為是邪惡的”嗎? )。

     token = +~char_("\\r\\n -"); values = +token; // entry = (lexeme['-' >> token] >> -values | attr("empty") >> values); args = *entry; // data = skip(qi::blank) [ token >> args ]; 

在下面的示例中,我使用了Fusion適應功能來啟用自動屬性傳播(該功能可立即啟用帶有

#define BOOST_SPIRIT_DEBUG

生活在Coliru

//#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <map>
#include <string>
#include <vector>

// Structure stores the parsed command line information:
struct CmdData
{
    typedef std::string               Name;

    typedef std::string               ArgName;
    typedef std::string               Value;

    typedef std::vector<Value>        Values;  // Type defines a list of values:
    typedef std::map<ArgName, Values> Args;    // Type defines a map storing the relation between a argument and the corresponding values:

    Name cmd; // Stores the command name as a string.
    Args arg; // Stores the arguments and the corresponding values as strings.
};

BOOST_FUSION_ADAPT_STRUCT(CmdData, (CmdData::Name, cmd)(CmdData::Args, arg))

namespace Grammar
{
    namespace qi = boost::spirit::qi;

    // This class implements the grammar used to parse a command line.
    // The expected format is as follows:
    // - command
    // - command value0 ... valueN
    // - command -arg0 ... -argN
    // - command -arg0 value0 ... valueN ... -argN value0 ... valueN
    template <typename It>
    struct decode : qi::grammar<It, CmdData()>
    {
        decode() : decode::base_type(data)
        {
            using namespace qi;

            token  = +~char_("\r\n -");
            values = +token;

            //
            entry  = (lexeme['-' >> token] >> -values | attr("empty") >> values);
            args   = *entry;

            //
            data   = skip(qi::blank) [ token >> args ];

            BOOST_SPIRIT_DEBUG_NODES( (token)(values)(entry)(args)(data) )
        }

      private:
        qi::rule<It, CmdData()> data;

        // The following variables define the rules used within this grammar:
        typedef std::pair<CmdData::ArgName, CmdData::Values> Entry;
        qi::rule<It, CmdData::Values(), qi::blank_type> values;
        qi::rule<It, Entry(),           qi::blank_type> entry;
        qi::rule<It, CmdData::Args(),   qi::blank_type> args;

        // lexemes
        qi::rule<It, std::string()> token;
    };

}   // namespace

bool parse(const std::string& in)
{
    CmdData data;

    // Create an instance of the used grammar:
    Grammar::decode<std::string::const_iterator> gr;

    // Try to parse the data stored within the stream according the grammar and store the result in the tag variable:
    bool b = boost::spirit::qi::parse(in.begin(), in.end(), gr, data);

    std::cout << "Parsing: '" << in << "' ok: " << std::boolalpha << b << "\n";
    if (b)
        std::cout << "Entries parsed: " << data.arg.size() << "\n";

    return b;
}

int main()
{
    parse("   cmd0");
    parse("   cmd0  -23.0 value0  value1  value2");
    parse("   cmd0  -arg0  -arg1  -arg2");
    parse("   cmd0  -arg0  value0  -arg1  value0  value1  -arg2  value0  value1  value2");
}

打印

Parsing: '   cmd0' ok: true
Entries parsed: 0
Parsing: '   cmd0  -23.0 value0  value1  value2' ok: true
Entries parsed: 1
Parsing: '   cmd0  -arg0  -arg1  -arg2' ok: true
Entries parsed: 3
Parsing: '   cmd0  -arg0  value0  -arg1  value0  value1  -arg2  value0  value1  value2' ok: true
Entries parsed: 3

(禁用調試輸出)


¹(例如,是否明確選擇-23.0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM