gpt4 book ai didi

c++ - 如何在 grammar 中添加 qi::symbols?

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:56:39 26 4
gpt4 key购买 nike

我正在尝试使用 Boost.Spirit (V. 2.5) 库来创建一个迷你计算器。我要实现的功能:- 有效的基本微积分(+、-、/、*)- 一些功能(如最小值、最大值)也可以使用- 声明/分配双变量,并且存在问题......当我添加“[vars.add]”时出现编译错误(模板参数不明确)。我已经尝试过“添加(char_(_1)”,“添加(_1)”,...但似乎没有任何效果。我显然遗漏了一些东西(实际上不理解一些东西)。如果有人可以帮助我,我会万分感谢!

这是来源:

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/home/phoenix/statement/if.hpp>
#include <boost/spirit/home/phoenix/bind/bind_function.hpp>

#include <iostream>
#include <string>

namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phx = boost::phoenix;

struct vars_ : qi::symbols<char, double> {
vars_() {
add("ans" , 0);
}
} vars;

template <typename Iterator>
struct parser : qi::grammar<Iterator, double()>
{
parser() : parser::base_type(function)
{
using qi::eps;
using qi::lit;
using qi::_val;
using qi::_1;
using ascii::char_;
using qi::double_;
using qi::string;
using qi::lexeme;
using boost::phoenix::if_;
using qi::alpha;
using qi::alnum;

MAX = lexeme[string("max") | string("MAX")]; //define max symbol

MIN = lexeme[string("min") | string("MIN")]; //define min symbol

D = lexeme[string("d") | string("D")]; //define distance symbol

ANS = lexeme[string("ans") | string("ANS")]; //not working yet

function =
expression [_val = _1]
| declaration
| assignment
| ( MAX >> "(" >> function [_val = _1] >>
+(',' >> function [if_(_1 > _val)[_val = _1]]) >> ')') // call : max(function,...)
| ( MIN >> "(" >> function [_val = _1] >>
+(',' >> function [if_(_1 < _val)[_val = _1]]) >> ')') // call : min(function,...)
| ( D >> "(" >> (function >> ',' >> function) >> ')'); // call : d(point1,point2) not implemented yet

expression =
term [_val = _1]
>> *( ('+' >> term [_val += _1])
| ('-' >> term [_val -= _1]));

term =
factor [_val = _1]
>> *( ('*' >> factor [_val *= _1])
| ('/' >> factor [_val /= _1]));
factor =
double_ [_val = _1]
| (vars [_val += _1] )
| '(' >> expression [_val = _1] >> ')'
| ('-' >> factor [_val = -_1])
| ('+' >> factor [_val = _1])
| declaration;
;

assignment =
vars >> '=' >> function;

var_decl =
lexeme [ qi::raw [ ( alpha >> *( alnum | '_' ) ) - vars ] ] //[ phx::bind(vars.add, _1) ]
;


declaration =
"var " >> var_decl >> *( ',' >> var_decl );
}

qi::rule<Iterator, double()> MAX, MIN, D, ANS, expression, term, factor,
function, assignment, var_decl, declaration;
};
}

///////////////////////////////////////////////////////////////////////////////
// Main program
///////////////////////////////////////////////////////////////////////////////
int main()
{
std::cout << "**********************************************************" << std::endl;
std::cout << "* *" << std::endl;
std::cout << "* Command interface for VideoTraction4 *" << std::endl;
std::cout << "* *" << std::endl;
std::cout << "**********************************************************" << std::endl << std::endl;
std::cout << "Type an expression...or [q or Q] to quit" << std::endl << std::endl;

typedef std::string::const_iterator iterator_type;
typedef client::parser<iterator_type> parser;

parser _parser; // Our grammar

std::string str;
double result;
while (std::getline(std::cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;

std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();

bool r = parse(iter, end, _parser, result);

if (r && iter == end)
{
std::cout << "-------------------------\n";
std::cout << "Parsing succeeded\n";
std::cout << "result = " << result << std::endl;
std::cout << "-------------------------\n";
client::vars.remove("ans");
client::vars.add("ans",result);
}
else
{
std::string rest(iter, end);
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "stopped at: \": " << rest << "\"\n";
std::cout << "-------------------------\n";
}
}

std::cout << "Bye... :-) \n\n";
return 0;
}

我想做这样的事情:

var i,j
i = 1
j = max(2*(i+1),5)

最佳答案

嗯,我自己从来没有真正直接从语义 Action 中添加符号(我更喜欢构建 AST,然后遍历它们)。

事实上你是这样写的并且没有 SSCCE让我措手不及了一会儿。事实证明,我应该忽略间接的“证据”,直接去找文档 + 赢:

var_decl =
qi::as_string [ lexeme [ ( ( alpha >> *( alnum | '_' ) ) - vars ) ] ]
[ phx::bind(vars.add, _1) ];

var_decl =
lexeme [ qi::raw [ ( alpha >> *( alnum | '_' ) ) - vars ] ]
[ phx::bind(vars.add, _1) ];

一些类似的咒语将适用

编辑这是完整的源代码,在 MSVC 2010 上编译,boost 1.47:

输出:

T:\>cl /EHsc /I "c:\Program Files (x86)\boost\boost_1_47" test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

test.cpp
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:test.exe
test.obj

T:\>.\test.exe
**********************************************************
* *
* Command interface for VideoTraction4 *
* *
**********************************************************

Type an expression...or [q or Q] to quit

3*4+7
-------------------------
Parsing succeeded
result = 19
-------------------------

稍微不相关的一点:var_decl 规则的公开属性似乎是 char 看起来有点有趣?

您可能想阅读自动规则和 %= 运算符;如果没有 %=,语义操作的存在将抑制所有自动属性传播。这在所需的定制点不存在的情况下很有用。如所写,暴露的属性将始终未分配给。

关于c++ - 如何在 grammar<Iterator,double()> 中添加 qi::symbols?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8780604/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com