如何添加qi ::符号在语法<迭代器,双()>? [英] How to add qi::symbols in grammar<Iterator,double()>?

查看:150
本文介绍了如何添加qi ::符号在语法<迭代器,双()>?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用Boost.Spirit(V. 2.5)库来创建一个小型计算器。特性我想实现:
- 基本演算(+, - ,/,*),工作
- 一些函数(如min,max),工作太多
- 声明/双变量,并有问题...当我添加[vars.add]我得到编译错误(模板参数ambiguious)。
我试过add(char _(_ 1),add(_1),...没有什么似乎工作,我显然缺少一些东西(不是真正理解的东西)。如果有人可以帮助我

I am trying to use Boost.Spirit (V. 2.5) library to create a mini-calculator. Features I want to implement : - basic calculus (+,-,/,*), that works - some functions (like min, max), that works too - declaring/assigning double variables, and there is the problem... when I add "[vars.add]" I get compilation error (template parameter ambiguious). I've tried "add(char_(_1)", "add(_1)",... and nothing seems to work. I am obviously missing something (not understanding something actually). If someone could help me on this I would me most gratefull!

这是源代码:

#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;
}

我想做一些事情,例如:

I would like to do things such as :

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


推荐答案

更喜欢构建AST,然后遍历那些)。

Huh, I've never actually added symbols from directly inside Semantic Actions myself (I prefer to build ASTs, and then traverse those).

这样写的事实,并且没有

The fact that you wrote it like this and the absence of a SSCCE had me blindsided for a moment. Turns out, I should just have ignored the circumstantial 'evidence' and went straight for the docs + win:

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) ];

和一些类似的咒语

编辑以下是使用boost 1.47在MSVC 2010上编译的完整源代码:

Edit Here is the complete source, compiled on MSVC 2010, with boost 1.47:

  • https://gist.github.com/1582163

输出:

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

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

You might want to read up on auto-rules and the %= operator; Without %=, the presence of a Semantic Action will suppress all automatic attribute propagation. That is helpful in case the required customization points do not exist. As written, the exposed attribute will always be unassigned-to.

这篇关于如何添加qi ::符号在语法&lt;迭代器,双()&gt;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆