gpt4 book ai didi

c++ - 灵气序列解析问题

转载 作者:搜寻专家 更新时间:2023-10-31 01:53:18 24 4
gpt4 key购买 nike

我在使用 Spirit::Qi 2.4 编写解析器时遇到了一些问题。我有一系列键值对以以下格式解析 <key name>=<value> .

键名可以是[a-zA-Z0-9]并且始终跟在 = 之后键名= 之间没有空格符号。 key 名称 也始终以至少一个空格开头。

Value 几乎可以是任何 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
(在带有 boost 1.50 的 VS 2012 下编译,但在较旧的设置上也应该没问题)。

最佳答案

我建议您看一下文章 Parsing a List of Key-Value Pairs Using Spirit.Qi .

大大简化了您的代码,同时

  • 添加属性处理
  • 去除凤凰语义 Action
  • 调试规则

废话不多说了:

#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)];

关于c++ - 灵气序列解析问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11340359/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com