灵奇序列解析问题(Spirit Qi sequence parsing issues)

2019-09-19 02:49发布

我有解析器的写作与精神::齐2.4的一些问题。 我有一系列的键-值对在下面的格式解析<key name>=<value>

密钥名称可以是[a-zA-Z0-9]和后面总是跟随=键名和之间没有空白标志=标志。 关键的名字也总是由至少一个空间之后。

几乎可以是任何C的表达(空格也是可能的),与含有表达除外=炭和码块{ }

在键值对的序列的末端有一个{标志。

我挣扎了很多与这个表达式解析器写。 由于密钥名称总是由至少一个空间之前和之后=和不包含空格我将其定义为

  KeyName %= [+char_("a-zA-Z0-9_") >> lit("=")] ;

值几乎可以是任何东西,但它不能包含=也不{字符,所以我把它定义为:

  Value %=  +(char_ - char_("{=")) ;

我想过用前瞻的这样搭上值:

ValueExpression 
    %= ( 
      Value  
      >> *space 
      >> &(KeyName | lit("{"))
    )
    ;

但它不会工作,出于某种原因(好像ValueExpression贪婪上升到=号和“不知道”怎么从那里做)。 我有限的LL解析器的知识,所以我真的不知道什么是烹调这里。 有没有我可以解决这种序列的任何其他方式?

下面是一系列示例:

EXP1=FunctionCall(A, B, C) TEST="Example String" \
AnotherArg=__FILENAME__ - 'BlahBlah' EXP2= a+ b+* {

附加信息:因为这是一个更大的语法的一部分,我不能真正解决这个问题不是由Spirit.Qi解析器(比如通过“=”分裂和做一些自定义分析或类似的东西)任何其他方式。

编辑:

我创建了最低工作例子在这里: http://ideone.com/kgYD8
(VS 2012下编译提升1.50,而应该是对旧的设置罚款以及)。

Answer 1:

我建议你看一下文章解析键值对使用Spirit.Qi的名单 。

我已经大大简化你的代码,而

  • 添加属性的处理
  • 除凤凰语义动作
  • 规则调试

这是,事不宜迟:

#define BOOST_SPIRIT_DEBUG

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <map>

namespace qi = boost::spirit::qi;
namespace fusion = boost::fusion;

typedef std::map<std::string, std::string> data_t;

template <typename It, typename Skipper>
struct grammar : qi::grammar<It, data_t(), Skipper>
{
    grammar() : grammar::base_type(Sequence)
    {
        using namespace qi;

        KeyName  = +char_("a-zA-Z0-9_") >> '=';
        Value    = qi::no_skip [+(~char_("={") - KeyName)];
        Sequence = +(KeyName > Value);

        BOOST_SPIRIT_DEBUG_NODE(KeyName);
        BOOST_SPIRIT_DEBUG_NODE(Value);
        BOOST_SPIRIT_DEBUG_NODE(Sequence);
    }
  private:
    qi::rule<It, data_t(), Skipper>      Sequence;
    qi::rule<It, std::string()>          KeyName; // no skipper, removes need for qi::lexeme
    qi::rule<It, std::string(), Skipper> Value;
};

template <typename Iterator>
data_t parse (Iterator begin, Iterator end)
{
    grammar<Iterator, qi::space_type> p;

    data_t data;

    if (qi::phrase_parse(begin, end, p, qi::space, data)) {
        std::cout << "parse ok\n";
        if (begin!=end) {
            std::cout << "remaining: " << std::string(begin,end) << '\n';
        }
    } else {
        std::cout << "failed: " << std::string(begin,end) << '\n';
    }

    return data;
}

int main ()
{
    std::string test(" ARG=Test still in first ARG ARG2=Zombie cat EXP2=FunctionCall(A, B C) {" );
    auto data = parse(test.begin(), test.end());

    for (auto& e : data)
        std::cout << e.first << "=" << e.second << '\n';
}

输出将是:

parse ok
remaining: {
ARG=Test still in first ARG 
ARG2=Zombie cat 
EXP2=FunctionCall(A, B C) 

如果你真的想要“{”是最后的价值的一部分,改变这一行:

Value    = qi::no_skip [+(char_ - KeyName)];


文章来源: Spirit Qi sequence parsing issues