如何让精神之气::as_string重复工作?
how to get spirit's qi::as_string to work with repeat?
由于一些奇怪的原因,我不能让qi::as_string[]
与repeat()[]
一起工作。
std::string str = { "{ +100S+++ ;n }" };
,我得到以下输出
PLUS OR MINUS+
THREE PLUS OR MINUS
PARSED FINE
-------------------------
Parsing succeeded
-------------------------
显示解析正常,捕获了第一个+
,但没有捕获随后的三个+++
。
注我只是想让three_plus_or_minus
捕获一到三个加号或减号一行作为字符串。不使用as_string[]
的替代解决方案也将受到赞赏。
我为长清单道歉,但我需要在实际代码中同时使用词法分析器和解析器。
// -------------- Third Party --------------
#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>
// -------------- C++ stdlib --------------
#include <iostream>
#include <fstream>
#include <string>
using namespace boost::spirit;
using boost::phoenix::val;
enum token_ids
{
ID_CONSTANT = 1000,
ID_INTEGER,
ID_TAG,
ID_IDENTIFIER
};
template <typename Lexer>
struct example6_tokens : lex::lexer<Lexer>
{
example6_tokens()
{
identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
constant = "[0-9]+";
tag = "sl|s|l|tl|SL|S|L|TSL|"
"z|r|i|Z|R|I|"
"<>|><|<<>>|>><<|><><|<><>";
this->self = lex::token_def<>('(') | ')' | '{' | '}'
| '=' | ';' | ':' | '+' | '-';
this->self.add
(constant, ID_CONSTANT )
(tag, ID_TAG )
(identifier, ID_IDENTIFIER )
;
this->self("WS")
= lex::token_def<>("[ \t\n]+")
| "\/\*[^*]*\*+([^/*][^*]*\*+)*\/"
| "\/\/[^n]*"
;
}
lex::token_def<std::string> identifier, tag;
lex::token_def<unsigned int> constant;
};
// ----------------------------------------------------------------------------
template <typename Iterator, typename Lexer>
struct example6_grammar
: qi::grammar<Iterator, qi::in_state_skipper<Lexer> >
{
template <typename TokenDef>
example6_grammar(TokenDef const& tok)
: example6_grammar::base_type(program)
{
using boost::spirit::_val;
program
= +block
;
block
= '{' >> *slsltl_stmt >> '}'
;
plus_or_minus
%= ( qi::as_string[ qi::lit( '+' ) ] | qi::as_string[ '-' ])
[
std::cout << val("PLUS OR MINUS") << val( _1 ) << "n"
]
;
three_plus_or_minus
%= ( qi::as_string[ repeat(1,3)['+'] ] | qi::as_string[ repeat(1,3)['-'] ] )
[
std::cout << val("THREE PLUS OR MINUS") << val( _1 ) << "n"
]
;
slsltl_stmt
= ( - plus_or_minus
>> token(ID_CONSTANT)
>> token(ID_TAG)
>> three_plus_or_minus
>> ';'
)
[
std::cout << val("PARSED FINE") << "n"
]
;
expression
= tok.identifier [ _val = _1 ]
| tok.constant [ _val = _1 ]
;
}
typedef boost::variant<unsigned int, std::string> expression_type;
qi::rule<Iterator, qi::in_state_skipper<Lexer> > program, block;
qi::rule<Iterator, std::string(), qi::in_state_skipper<Lexer> >
plus_or_minus, three_plus_or_minus;
qi::rule<Iterator, std::string(), qi::in_state_skipper<Lexer> > slsltl_stmt;
qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> > expression;
};
int
main( int argv, char* argc[] )
{
typedef std::string::iterator base_iterator_type;
typedef lex::lexertl::token<
base_iterator_type, boost::mpl::vector<unsigned int, std::string>
> token_type;
typedef lex::lexertl::lexer<token_type> lexer_type;
typedef example6_tokens<lexer_type> example6_tokens;
typedef example6_tokens::iterator_type iterator_type;
typedef example6_grammar<iterator_type, example6_tokens::lexer_def> example6_grammar;
example6_tokens tokens; // Our lexer
example6_grammar calc(tokens); // Our parser
std::string str = { "{ +100S+++ ;n }" };
std::string::iterator it = str.begin();
iterator_type iter = tokens.begin(it, str.end());
iterator_type end = tokens.end();
std::string ws("WS");
bool r = qi::phrase_parse(iter, end, calc, qi::in_state(ws)[tokens.self]);
if (r && iter == end)
{
std::cout << "-------------------------n";
std::cout << "Parsing succeededn";
std::cout << "-------------------------n";
}
else
{
std::cout << "-------------------------n";
std::cout << "Parsing failedn";
std::cout << "-------------------------n";
}
}
Try
slsltl_stmt %= /*....*/;
代替slsltl_stmt =
。使用语义操作禁用自动属性传播。
(我还没有看你的代码的其余部分。可能有更多的地方需要适应这个/其他东西)
编辑
我做了更多的测试,认为这是你所期望的:
three_plus_or_minus
= (qi::as_string[ repeat(1,3)[qi::char_('+')] | repeat(1,3)[qi::char_('-')] ])
[ std::cout << val("THREE PLUS OR MINUS") << _1 << "n" ]
;
一个开箱即用的问题:你为什么要使用Lexer?为+++
设置一个标记不是很有意义吗?
相关文章:
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- <string> 结构中的矢量无法正常工作
- string.find() 无法正常工作
- std::string::擦除没有按我预期工作
- 'const std::string&s = nullptr' 如何作为可选参数工作
- `std :: string :: find_last_of()如何实际工作
- std::string 上的 substr 无法正常工作,因为存在一些不可见但看起来像空格的字符
- "string::erase"如何在 cpp 中工作?
- std::string 赋值运算符如何工作
- 我在不使用string.h的情况下写了一个C++回文.在没有 Do-While 循环的情况下,它可以正常工作.但是当我尝
- std::string::find在c++中未按预期工作
- c ++比较std::string将无法工作,如果我不使用Code::Blocks但cygwin编译
- 采用“std::string”的显式构造函数得到“char*”,工作正常
- getline(cin,string)与cin.ignore()一起不工作
- basename-freebsd使用std::string可以正常工作,但不使用
- c++转换为String最终停止工作
- std::atomic<std::string> 是否正常工作?
- 我的指向 std::string 对象的指针列表无法正常工作,我无法弄清楚为什么
- Std::string不能与Std::set一起工作