精神齐序列解析问题 [英] Spirit Qi sequence parsing issues
问题描述
我有解析器写作与精神::齐2.4的一些问题。
我有一系列的键 - 值对的格式如下解析<键名称> = LT;价值方式>
I have some issues with parser writing with Spirit::Qi 2.4.
I have a series of key-value pairs to parse in following format <key name>=<value>
.
的键名称的可以是 [A-ZA-Z0-9]
键,总是跟着 =
与键名称和 =
符号之间没有空格符号。 键名称的也总是$ P $至少有一个空间pceded。
Key name can be [a-zA-Z0-9]
and is always followed by =
sign with no white-space between key name and =
sign. Key name is also always preceded by at least one space.
的值的几乎可以是任何C EX pression(空格也是可能的),含恩pressions除外 =
char和code块 {}
。
Value can be almost any C expression (spaces are possible as well), with the exception of the expressions containing =
char and code blocks { }
.
在键值对的序列的末端有一个 {
标志。
At the end of the sequence of the key value pairs there's a {
sign.
我奋斗了很多写作解析器这个前pression。由于密钥名称始终是由至少一个空格pceded其次为 =
$ P $,并且不包含空格我把它定义为
I struggle a lot with writing parser for this expression. Since the key name always is preceded by at least one space and followed by =
and contains no spaces I defined it as
KeyName %= [+char_("a-zA-Z0-9_") >> lit("=")] ;
值几乎可以是任何东西,但它不能包含 =
也不 {
字符,所以我把它定义为
Value can be almost anything, but it can not contain =
nor {
chars, so I defined it as:
Value %= +(char_ - char_("{=")) ;
我想过用前瞻的这样搭上了值:
I thought about using look-ahead's like this to catch the value:
ValueExpression
%= (
Value
>> *space
>> &(KeyName | lit("{"))
)
;
但它不会工作,出于某种原因(好像 ValueEx pression
贪婪上升到 =
号和不知道怎么从那里做)。我有限的LL解析器的知识,所以我真的不知道什么是烹调这里。有没有我可以解决这种序列的任何其他方式?
But it won't work, for some reason (seems like the ValueExpression
greedily goes up to the =
sign and "doesn't know" what to do from there). I have limited knowledge of LL parsers, so I'm not really sure what's cooking here. Is there any other way I could tackle this kind of sequence?
下面的例子系列:
EXP1=FunctionCall(A, B, C) TEST="Example String" \
AnotherArg=__FILENAME__ - 'BlahBlah' EXP2= a+ b+* {
其他信息:,因为这是一个更大的语法中的一部分,我不能真正解决这个问题不是由Spirit.Qi解析器(像'='和分裂做任何其他方式一些自定义的分析或类似的东西)。
Additional info: since this is a part of a much larger grammar I can't really solve this problem any other way than by a Spirit.Qi parser (like splitting by '=' and doing some custom parsing or something similar).
编辑:
我已经在这里创造最低工作例如: http://ideone.com/kgYD8 结果
(VS 2012在编译提升1.50,而应该是在旧的设置罚款以及)。
I've created minimum working example here: http://ideone.com/kgYD8
(compiled under VS 2012 with boost 1.50, but should be fine on older setups as well).
推荐答案
我建议你看看文章<一个href=\"http://boost-spirit.com/home/articles/qi-example/parsing-a-list-of-key-value-pairs-using-spirit-qi/\"相对=nofollow>解析键值对使用Spirit.Qi 的List。
I'd suggest you have a look at the article Parsing a List of Key-Value Pairs Using Spirit.Qi.
我的极大地的简化您的code,而
I've greatly simplified your code, while
- 添加属性处理
- 删除凤语义动作
- 规则调试
这,事不宜迟:
#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)
如果你真的想要'{'是最后的价值的一部分,改变这一行:
If you really wanted '{' to be part of the last value, change this line:
Value = qi::no_skip [+(char_ - KeyName)];
这篇关于精神齐序列解析问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!