防止 Boost Spirit Symbol 解析器过早接受关键字
Posted
技术标签:
【中文标题】防止 Boost Spirit Symbol 解析器过早接受关键字【英文标题】:Prevent the Boost Spirit Symbol parser from accepting a keyword too early 【发布时间】:2014-03-24 11:41:00 【问题描述】:如何防止 Boost Spirit Symbol 解析器在以有效关键字(符号)开头时接受关键字(符号)。我希望该构造无法整体解析“ONEMORE”并且无法成功解析“ONE”,因为这是一个有效的关键字,然后在“MORE”上失败。
下面是代码的实际输出:
Keyword as a number: 1
Keyword as a number: 2
Keyword as a number: 1
Invalid keyword: MORETHREE
这就是我喜欢的样子:
Keyword as a number: 1
Keyword as a number: 2
Invalid keyword: ONEMORE
Keyword as a number: 3
代码只是说明问题的一个示例。
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>
using namespace std;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
void printNumber( unsigned u )
cout << "Keyword as a number: " << u << endl;
void printInvalidKeyword( const string &s )
cout << "Invalid keyword: " << s << endl;
template <typename Iterator>
struct keyword_parser : qi::grammar<Iterator, ascii::space_type>
struct mySymbols_ : qi::symbols<char, unsigned>
mySymbols_()
add
("ONE" , 1)
("TWO" , 2)
("THREE" , 2)
;
mySymbols;
keyword_parser() : keyword_parser::base_type(start)
using qi::_1;
using qi::raw;
using ascii::char_;
start %= *(
mySymbols[&printNumber]
|
invalid[&printInvalidKeyword]
);
invalid = +char_;
qi::rule<Iterator, ascii::space_type> start;
qi::rule<Iterator, std::string(), ascii::space_type> invalid;
;
int main()
using boost::spirit::ascii::space;
typedef std::string::const_iterator iterator_type;
typedef keyword_parser<iterator_type> keyword_parser;
std::string s = "ONE TWO ONEMORE THREE";
iterator_type b = s.begin();
iterator_type e = s.end();
phrase_parse(b, e, keyword_parser(), space);
return 0;
【问题讨论】:
【参考方案1】:看qi::repository::distinct
或自己采取一些措施:
start %= *(
keyword [cout << val("Keyword as a number: ") << _1 << endl]
| invalid [cout << val("Invalid keyword: ") << _1 << endl]
);
keyword = mySymbols >> !(char_("a-zA-Z0-9_"));
invalid = +ascii::graph;
被声明为的规则
qi::rule<Iterator, ascii::space_type> start;
// lexemes do not ignore embedded skippables
qi::rule<Iterator, int()> keyword;
qi::rule<Iterator, std::string()> invalid;
看Live On Coliru
打印:
Keyword as a number: 1
Keyword as a number: 2
Invalid keyword: ONEMORE
Keyword as a number: 2
完整来源:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <string>
using namespace std;
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
struct keyword_parser : qi::grammar<Iterator, ascii::space_type>
struct mySymbols_ : qi::symbols<char, unsigned>
mySymbols_()
add
("ONE" , 1)
("TWO" , 2)
("THREE" , 2)
;
mySymbols;
keyword_parser() : keyword_parser::base_type(start)
using qi::_1;
using ascii::char_;
using phx::val;
start %= *(
keyword [cout << val("Keyword as a number: ") << _1 << endl]
| invalid [cout << val("Invalid keyword: ") << _1 << endl]
);
keyword = mySymbols >> !(char_("a-zA-Z0-9_"));
invalid = +ascii::graph;
qi::rule<Iterator, ascii::space_type> start;
// lexemes do not ignore embedded skippables
qi::rule<Iterator, int()> keyword;
qi::rule<Iterator, std::string()/*IMPLICIT LEXEME:, ascii::space_type*/> invalid;
;
int main()
using boost::spirit::ascii::space;
typedef std::string::const_iterator iterator_type;
typedef keyword_parser<iterator_type> keyword_parser;
std::string s = "ONE TWO ONEMORE THREE";
iterator_type b = s.begin();
iterator_type e = s.end();
phrase_parse(b, e, keyword_parser(), space);
return 0;
【讨论】:
有些事情很简单,除非你看不到它:-) 谢谢。以上是关于防止 Boost Spirit Symbol 解析器过早接受关键字的主要内容,如果未能解决你的问题,请参考以下文章