我目前正在开发一种基于Spirit的表达式解析器,该解析器应最终(在很远的将来)允许这样的表达式
"a*b*c"
"10+20*x.y.z"
"a.b.c[ a.b ][ e.c( d.e()*4 )].e.f( (a.b+23)*d, -23*b.e(a.b.c) ).x.y"
成员访问,数组订阅,函数调用和表达式的混合
[] -> subscription
() -> function call or expression bracket
. member chaining
目前我正在与成员链跳过的空间作斗争
"a . b . c"
在我的世界中无效-但是由于空间跳过功能而被解析
在线尝试我减少的样本:https://wandbox.org/permlink/o5kcYtUQEfKZqJgw
问题是第23行:
qi::rule<std::string::iterator, qi::blank_type, utree()> identifier_chain
= identifier >> *('.' >> identifier);
我不能绕着规则使用qi::lexeme,我将得到一个无法转换为Skipper的编译错误
但是如果我将完整的标识符规则复制到identifier_chain规则中就可以使用
qi::rule<std::string::iterator, qi::blank_type, utree()> identifer_chain
= qi::lexeme[qi::ascii::alpha >> *(qi::ascii::alnum | '_')
>> *('.' >> qi::ascii::alpha >> *(qi::ascii::alnum | '_'))];
但这似乎很多余,我认为在解析器不断增长的将来,复制将使我陷入麻烦
任何关于如何使用lexeme或其他方式保持我的''的想法。连接没有空格
这样订阅结束和成员链接紧密连接
].a
a.b
那是我的解析器中唯一不希望空间跳过的地方,这是减少解析器代码的理想选择
thx的任何帮助/提示
最佳答案
这是船长的工作方式(请参阅Boost spirit skipper issues)
您的规则声明了船长:
qi::rule<std::string::iterator, qi::blank_type, utree()> identifier_chain;
因此,要禁止它,您可以用lexeme包围,但是您也可以从声明中删除船长。标识符规则实际上也是如此,因为它也完全包装在
lexeme[]
中。建议的最小修补程序:
Live On Coliru
#include <iostream>
#include <iomanip>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_utree.hpp>
namespace qi = boost::spirit::qi;
using boost::spirit::utree;
int main() {
auto tests = std::vector<std::string>{
"a", // ok
"a.b", // ok
" a.b ", // ok
"a . b", // error
"a . b. c" // error
};
for (std::string const str : tests) {
auto iter = str.begin(), end = str.end();
qi::rule<std::string::const_iterator, utree()>
identifier = qi::ascii::alpha >> *(qi::ascii::alnum | '_'),
identifier_chain = identifier >> *('.' >> identifier);
utree ut;
bool r = qi::phrase_parse(iter, end, identifier_chain >> qi::eoi, qi::blank, ut);
std::cout << std::quoted(str) << " ";
if (r) {
std::cout << "OK: " << ut << "\n";
} else {
std::cout << "Failed\n";
}
if (iter!=end) {
std::cout << "Remaining unparsed: " << std::quoted(std::string(iter,end)) << "\n";
}
std::cout << "----\n";
}
return 0;
}
打印品:
"a" OK: ( "a" )
----
"a.b" OK: ( "a" "b" )
----
" a.b " OK: ( "a" "b" )
----
"a . b" Failed
Remaining unparsed: "a . b"
----
"a . b. c" Failed
Remaining unparsed: "a . b. c"
----
关于c++ - 使用qi::lexeme解析 '.'链式标识符列表,并防止空间跳过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60819236/