我有解析器的写作与精神::齐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,而应该是对旧的设置罚款以及)。
我建议你看一下文章解析键值对使用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)];