我试图像下面的树表达式一样解析C函数(使用Spirit Parser Framework):
F( A() , B( GREAT( SOME , NOT ) ) , C( YES ) )
Run Code Online (Sandbox Code Playgroud)
为此,我试图使用以下语法的三个规则:
template< typename Iterator , typename ExpressionAST >
struct InputGrammar : qi::grammar<Iterator, ExpressionAST(), space_type> {
InputGrammar() : InputGrammar::base_type( ) {
tag = ( qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") )[ push_back( at_c<0>(qi::_val) , qi::_1 ) ];
command = tag [ at_c<0>(qi::_val) = at_c<0>(qi::_1) ] >> "(" >> (*instruction >> ",")
[ push_back( at_c<1>(qi::_val) , qi::_1 ) ] >> ")";
instruction = ( command …Run Code Online (Sandbox Code Playgroud) 我想了解在boost :: spirit :: qi的引擎下究竟发生了什么.假设我们有简单的解析器,它解析并计算由数字和加/减操作组成的表达式:
int main()
{
std::string INPUT_DATA = "12e-1 + 3.4 - .67";
typedef std::string::iterator iterator_type;
iterator_type begin = std::begin(INPUT_DATA);
iterator_type end = std::end(INPUT_DATA);
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::qi::ascii;
auto parser = qi::double_[qi::_val = qi::_1] // (1)
>> *(
(qi::lit('+') >> qi::double_[qi::_val += qi::_1]) // (2)
|
(qi::lit('-') >> qi::double_[qi::_val -= qi::_1]) // (3)
);
double result;
bool ok = qi::phrase_parse(begin, end, parser, ascii::space, result);
if ( ok && begin == end)
{
std::cout …Run Code Online (Sandbox Code Playgroud) 我\xca\xbcm 正在尝试创建基于Boost.Spirit.Qi 的解析。有一个像calc_utree这样的例子,我试图扩展用作语义操作的内容。
\n\n例如,通过单独的分配作为语义动作重用相同的方法是很简单的
\n\n term =\n factor [_val = _1]\nRun Code Online (Sandbox Code Playgroud)\n\n正如示例中的字面意思。但是,当我尝试将两者传递到规则定义外部的函数(方法)中,或者甚至将其写为 lambda 时,例如
\n\n term =\n factor [([&] {_val = _1; })]\nRun Code Online (Sandbox Code Playgroud)\n\n它会在该位置导致静默误分配:_val保持不变(编译器没有任何错误或警告)。如果我把它改成类似的东西也是一样
term =\n factor [do_term_factor(_val, _1)]\n<...>\ntemplate <typename D, typename S>\nD& do_term_factor(D& d, S& s) {\n d = s;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n似乎 I\xca\xbcve 陷入了对Qi和 的主要误解Phoenix。问题是(基本上它们是同一问题的不同形式):
Phoenix它们在 C++ lambda 中不\xca\xbct 工作的变量有什么具体之处?或者,如果_val没有 ,如何实现Phoenix?Spirit文档在这方面似乎相当晦涩。
环境详细信息:Boost …
我是错误"LNK1179:无效或损坏的文件:重复COMDAT"的受害者,这些 来源让我相信,通过不使用phoenix我可以避免此错误.
(这是我之前的问题的后续行动.)我想boost::phoenix用其他东西替换.也许,boost::bind但我不知道如何让它访问karma::_val.
以下代码无法在VC9上编译
错误C2825:'F':当后跟'::'时必须是类或命名空间
#include <boost/config/warning_disable.hpp>
#include <boost/foreach.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
#include <list>
namespace karma = boost::spirit::karma;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
class Item
{
public:
typedef std::vector<int> Values;
Item(const std::string & i, const Values & v) : m_id(i), m_values(v) {}
std::string getId() const { …Run Code Online (Sandbox Code Playgroud)