boost:spirit::qi 解析器使用多种语法和 phoenix::construct
boost:spirit::qi parser using multiple grammars and phoenix::construct
我在编写使用另一种 Qi 语法的 Qi 语法时遇到问题。这里提出了一个类似的问题,但我也在尝试使用 phoenix::construct,并且遇到编译困难。
这是我正在尝试做的事情的简化版本。我意识到此示例可能可以使用BOOST_FUSION_ADAPT_STRUCT
轻松完成,但我的实际代码处理更复杂的对象类型,因此我希望有一种方法可以使用语义操作来实现这一点。
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_container.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <cstdlib>
#include <iostream>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
// grammar for real numbers
template <typename Iterator>
struct Real : qi::grammar<Iterator, long double()>
{
qi::rule<Iterator, long double()> r;
Real() : Real::base_type(r)
{
r %= qi::long_double;
}
};
// grammar for complex numbers of the form a+bi
template <typename Iterator>
struct Complex : qi::grammar<Iterator, std::complex<long double>()>
{
qi::rule<Iterator, std::complex<long double>()> r;
Real<Iterator> real;
Complex() : Complex::base_type(r)
{
r = real [qi::_a = qi::_1] >> (qi::lit("+") | qi::lit("-"))
>> real [qi::_b = qi::_1] >> -qi::lit("*") >> qi::lit("i")
[
qi::_val = phx::construct<std::complex<long double> >(qi::_a, qi::_b)
];
}
};
int main()
{
// test real parsing
std::cout << "Parsing '3'" << std::endl;
std::string toParse = "3";
Real<std::string::iterator> real_parser;
long double real_val;
std::string::iterator beginIt = toParse.begin();
std::string::iterator endIt = toParse.end();
bool r = qi::parse(beginIt, endIt, real_parser, real_val);
if(r && beginIt == endIt)
std::cout << "Successful parse: " << real_val << std::endl;
else
std::cout << "Could not parse" << std::endl;
// test complex parsing
std::cout << "Parsing '3+4i'" << std::endl;
toParse = "3+4i";
Complex<std::string::iterator> complex_parser;
std::complex<long double> complex_val;
beginIt = toParse.begin();
endIt = toParse.end();
r = qi::parse(beginIt, endIt, complex_parser, complex_val);
if(r && beginIt == endIt)
std::cout << "Successful parse: " << real_val << std::endl;
else
std::cout << "Could not parse" << std::endl;
}
我能够使用 Spirit 文档中演示的phrase_parse方法解析 Complex,但我希望能够轻松地将 Complex 语法集成到其他解析器(例如表达式解析器)中。我是否缺少一些东西,可以让我将真实和复杂对象解析为不同的实体,同时仍然能够在其他规则/语法中有效地使用它们?
qi::_a
和qi::_b
表示规则的第一个和第二个局部变量。仅当您在规则r
的声明中添加qi::locals<long double, long double>
作为模板参数时,这些变量才可用(在这种情况下也可用于qi::grammar...
因为传递给语法构造函数的开始规则需要与语法兼容,即具有相同的模板参数)。
下面您可以看到另一种不需要局部变量的替代方案:
// grammar for complex numbers of the form a+bi
template <typename Iterator>
struct Complex : qi::grammar<Iterator, std::complex<long double>()>
{
qi::rule<Iterator, std::complex<long double>()> r;
Real<Iterator> real;
Complex() : Complex::base_type(r)
{
r = (
real >> (qi::lit("+") | qi::lit("-"))
>> real >> -qi::lit("*") >> qi::lit("i")
)
[
qi::_val = phx::construct<std::complex<long double> >(qi::_1, qi::_2)
];
}
};
在这种情况下,语义操作附加到整个解析器序列,我们可以使用_N占位符获取所需的属性。在这里,qi::_1 是指第一个 Real 解析器匹配的属性,qi::_2 是指第二个 Real 解析器匹配的属性。
使用任何替代方案,我们可以正常使用这些语法:
//using complex_parser, real_parser, complex_val and real_val declared in your code
std::cout << "Parsing 'variable=3+4i-2'" << std::endl;
toParse = "variable=3+4i-2";
beginIt = toParse.begin();
endIt = toParse.end();
std::string identifier;
r = qi::parse(beginIt, endIt, *qi::char_("a-z") >> '=' >> complex_parser >> '-' >> real_parser, identifier, complex_val, real_val);
if(r && beginIt == endIt)
std::cout << "Successful parse: " << identifier << complex_val.real() << " " << complex_val.imag() << " " << real_val << std::endl;
else
std::cout << "Could not parse" << std::endl;
相关文章:
- 1d 智能指针不适用于语法 (*)++
- 助记符和指向成员语法的指针
- 有人能分解一下这个c++模板的语法吗
- C++避免重复声明的语法是什么
- QMetaObject invokeMethod的基于函数指针的语法
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 单独定义模板化嵌套类方法的正确语法
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- 错误 C2760:语法错误:映射迭代器上意外的标记"标识符",预期的";"
- 为什么我会收到错误 C2143 语法错误:缺少"*"之前的';'?
- 奇怪的代码抛出编译错误模板< J,int aSize=10> C2143:语法错误:在"<"之前缺少";"
- 使用基类指针调用基类的值构造函数的语法是什么?
- 很好的语法来获取对向量/数组数据的大小引用?
- C++语法运算符功能?
- C++使用 rand 定义函数语法
- 什么文件可以修改 atom 的C++语法?
- 创建模板嵌套类实例的语法?
- boost:spirit::qi 解析器使用多种语法和 phoenix::construct
- 在 Qi 中使用 Boost Phoenix 在语法中引用以前的匹配项