gpt4 book ai didi

c++ - Boost Spirit 信号成功解析,尽管 token 不完整

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:15:13 25 4
gpt4 key购买 nike

我有一个非常简单的路径构造,我正在尝试使用 boost spirit.lex 进行解析。

我们有以下语法:

token := [a-z]+
path := (token : path) | (token)

所以我们在这里只讨论冒号分隔的小写 ASCII 字符串。

我有三个示例“xyz”、“abc:xyz”、“abc:xyz:”。

前两个应该被认为是有效的。第三个以冒号结尾,不应被视为有效。不幸的是,我的解析器认为这三个都是有效的。语法不应允许空标记,但显然 spirit 正在这样做。我错过了什么让第三个被拒绝?

此外,如果您阅读下面的代码,在注释中有另一个版本的解析器要求所有路径以分号结尾。当我激活这些行时,我可以获得适当的行为(即拒绝“abc:xyz:;”),但这并不是我真正想要的。

有人有什么想法吗?

谢谢。

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

#include <iostream>
#include <string>

using namespace boost::spirit;
using boost::phoenix::val;

template<typename Lexer>
struct PathTokens : boost::spirit::lex::lexer<Lexer>
{
PathTokens()
{
identifier = "[a-z]+";
separator = ":";

this->self.add
(identifier)
(separator)
(';')
;
}
boost::spirit::lex::token_def<std::string> identifier, separator;
};


template <typename Iterator>
struct PathGrammar
: boost::spirit::qi::grammar<Iterator>
{
template <typename TokenDef>
PathGrammar(TokenDef const& tok)
: PathGrammar::base_type(path)
{
using boost::spirit::_val;
path
=
(token >> tok.separator >> path)[std::cerr << _1 << "\n"]
|
//(token >> ';')[std::cerr << _1 << "\n"]
(token)[std::cerr << _1 << "\n"]
;

token
= (tok.identifier) [_val=_1]
;

}
boost::spirit::qi::rule<Iterator> path;
boost::spirit::qi::rule<Iterator, std::string()> token;
};


int main()
{
typedef std::string::iterator BaseIteratorType;
typedef boost::spirit::lex::lexertl::token<BaseIteratorType, boost::mpl::vector<std::string> > TokenType;
typedef boost::spirit::lex::lexertl::lexer<TokenType> LexerType;
typedef PathTokens<LexerType>::iterator_type TokensIterator;
typedef std::vector<std::string> Tests;

Tests paths;
paths.push_back("abc");
paths.push_back("abc:xyz");
paths.push_back("abc:xyz:");
/*
paths.clear();
paths.push_back("abc;");
paths.push_back("abc:xyz;");
paths.push_back("abc:xyz:;");
*/
for ( Tests::iterator iter = paths.begin(); iter != paths.end(); ++iter )
{
std::string str = *iter;
std::cerr << "*****" << str << "*****\n";

PathTokens<LexerType> tokens;
PathGrammar<TokensIterator> grammar(tokens);

BaseIteratorType first = str.begin();
BaseIteratorType last = str.end();

bool r = boost::spirit::lex::tokenize_and_parse(first, last, tokens, grammar);

std::cerr << r << " " << (first==last) << "\n";
}
}

最佳答案

除了 llonesmiz 已经说过的内容,还有一个使用 qi::eoi 的技巧,我有时会用到:

path = (
(token >> tok.separator >> path) [std::cerr << _1 << "\n"]
| token [std::cerr << _1 << "\n"]
) >> eoi;

这使得语法在成功匹配结束时require eoi(输入结束)。这导致了预期的结果:

http://liveworkspace.org/code/23a7adb11889bbb2825097d7c553f71d

*****abc*****
abc
1 1
*****abc:xyz*****
xyz
abc
1 1
*****abc:xyz:*****
xyz
abc
0 1

关于c++ - Boost Spirit 信号成功解析,尽管 token 不完整,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12864978/

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