Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何向boost::spirit计算器之一添加对指数运算符的支持?_C++_Boost_Grammar_Boost Spirit Qi - Fatal编程技术网

C++ 如何向boost::spirit计算器之一添加对指数运算符的支持?

C++ 如何向boost::spirit计算器之一添加对指数运算符的支持?,c++,boost,grammar,boost-spirit-qi,C++,Boost,Grammar,Boost Spirit Qi,我试图将指数运算符添加到这个boost::spirit计算器中,其语法如下所示。请注意,像“-2^2^3”这样的表达式必须解析为“-(2^(2^3))”=-256 阅读文档后,我的理解是,我必须在语法中插入以下指数表达式规则,以便它使用正确的从右到左关联性解析指数运算: 如果规则是: qi::rule<Iterator, ast::expression(), ascii::space_type> expr, equality_expr, relational_expr

我试图将指数运算符添加到这个boost::spirit计算器中,其语法如下所示。请注意,像“-2^2^3”这样的表达式必须解析为“-(2^(2^3))”=-256

阅读文档后,我的理解是,我必须在语法中插入以下指数表达式规则,以便它使用正确的从右到左关联性解析指数运算:

如果规则是:

    qi::rule<Iterator, ast::expression(), ascii::space_type>
    expr, equality_expr, relational_expr,
    logical_expr, additive_expr, multiplicative_expr, exponential_expr
    ;

    qi::rule<Iterator, ast::operand(), ascii::space_type>
    unary_expr, primary_expr
    ;

    qi::rule<Iterator, ast::function_call(), ascii::space_type >
    function_call
    ;

    qi::rule<Iterator, std::list<ast::expression>(), ascii::space_type >
    argument_list
    ;

    qi::rule<Iterator, std::string(), ascii::space_type>
    identifier
    ;

    qi::symbols<char, ast::optoken>
    equality_op, relational_op, logical_op,
    additive_op, multiplicative_op, unary_op, exponential_op
    ;

    qi::symbols<char>
    keywords
    ;
qi::规则
表达式,相等表达式,关系表达式,
逻辑表达式、加法表达式、乘法表达式、指数表达式
;
齐:规则
一元表达式,主表达式
;
齐:规则
函数调用
;
qi::rule]'表达式。cpp:4:37:此处为必填项
/usr/include/boost/spirit/home/qi/detail/assign\u to.hpp:152:13:错误:
没有用于调用的匹配函数
'计算器::ast::表达式::表达式(常量)
boost::variant,
boost::递归_包装器,
boost::recursive_wrapper>&)'
/usr/include/boost/spirit/home/qi/detail/assign\u to.hpp:152:13:注:
候选人:在文件中包括从
/计算器/表达式.hpp:20:0,
从计算器/表达式定义hpp:1,
from Expression.cpp:1:./calculator/Ast.hpp:83:12:注意:calculator::Ast::Expression::Expression()
./calculator/Ast.hpp:83:12:注意:候选者需要0个参数,1个
提供./计算器/Ast.hpp:83:12:注:
计算器::ast::表达式::表达式(常量)
计算器::ast::表达式(&)/calculator/ast.hpp:83:12:注:否
参数1从“常量”的已知转换
boost::variant,
boost::递归_包装器,
boost::recursive_wrapper>'to'常量
计算器::ast::表达式&'./计算器/ast.hpp:83:12:注意:
计算器::ast::表达式::表达式(计算器::ast::表达式&)
./calculator/Ast.hpp:83:12:注意:参数1没有已知的转换
从“const boost::variant”,
boost::递归_包装器,
boost::recursive_wrapper>'到
'计算器::ast::表达式&&'


我还没有完全测试过它,但我认为下面的修改提供了您想要的功能。请记住,此版本的计算器使用int作为其唯一类型,因此您将无法使用负指数,并且存在溢出的危险

  • ast.hpp
    您需要向枚举添加新元素(
    op_exp
    optoken

    ...
    op_times,
    op_divides,
    op_exp,    //ADDED //Line 55
    op_positive,
    ...
    
  • 表达式.hpp
    您需要为
    指数运算表达式
    指数运算数
    指数运算
    添加声明:

    qi::rule<Iterator, ast::expression(), ascii::space_type>
        expr, equality_expr, relational_expr,
        logical_expr, additive_expr, multiplicative_expr, exponential_expr //MODIFIED
        ;
    
    qi::rule<Iterator, ast::operand(), ascii::space_type>
        unary_expr, primary_expr, exponential_operand //MODIFIED
        ;
    ...
    qi::symbols<char, ast::optoken>
        equality_op, relational_op, logical_op,
        additive_op, multiplicative_op, exponential_op, unary_op //MODIFIED
        ;
    
  • 编译器.cpp
    您需要在
    program::print\u assembler
    compiler::operator()
    中的开关中添加新的大小写:

  • vm.hpp
    您需要将新元素(
    op_exp
    )添加到枚举
    byte_code

    ...
    op_mul,         //  multiply top two stack entries
    op_div,         //  divide top two stack entries
    op_exp,         //ADDED //Line 24
    
    op_not,         //  boolean negate the top stack entry
    ...
    
  • vm.cpp
    您需要在
    vmachine::execute
    中的开关中添加一个新的case(我只是简单地使用了std::pow,包括前面的cmath):


  • 您可以找到对
    calc6.cpp
    (最后一个适合单个cpp文件的编译器示例)的修改,它也有相同的功能(使用了非常详细的命名规则和硬编码的表达式)。我稍后将对其进行测试,只是让我说,经过一段时间的工作,我似乎已经完成了相同的操作,并且给出了语法表达式,如“-2^2^3”被解析为(-2)^(2^3),而不是它应该被解析为-(2^(2^3))。我会尽快确认这一点。还要注意,calc6的语法与calc8不同。后者是我需要帮助的。基本上,expential_expr规则位于一元_expr之前,因此您为calc8提出的语法错误地将上述示例解析为(-2)^[…]。calc6看起来不错,但它是另一个计算器。顺便说一句,你不是想写“指数表达式=一元表达式>>*(指数表达式)?在它的当前状态下,语法赋予一元运算符更高的优先级,而不是指数运算符,但这只是我的疏忽,我认为它(适度地)很容易反转(我会尝试)。我不确定你关于指数表达式的问题,但我认为我使用的是正确的。对“expression.hpp”和“expression.def.hpp”添加了新的更改。我相信它是有效的,但你应该彻底测试它。
    qi::rule<Iterator, ast::expression(), ascii::space_type>
        expr, equality_expr, relational_expr,
        logical_expr, additive_expr, multiplicative_expr, exponential_expr //MODIFIED
        ;
    
    qi::rule<Iterator, ast::operand(), ascii::space_type>
        unary_expr, primary_expr, exponential_operand //MODIFIED
        ;
    ...
    qi::symbols<char, ast::optoken>
        equality_op, relational_op, logical_op,
        additive_op, multiplicative_op, exponential_op, unary_op //MODIFIED
        ;
    
    ...
    multiplicative_op.add
        ("*", ast::op_times)
        ("/", ast::op_divide)
        ;       
    exponential_op.add      //ADDED //Line 69
    ("^", ast::op_exp)
    ;
    ...
    multiplicative_expr =       
            unary_expr
        >> *(multiplicative_op > unary_expr)
        ;
    
    unary_expr =    //MODIFIED
            exponential_operand
        |   (unary_op > exponential_operand)
        ;
    
    exponential_operand = exponential_expr; //ADDED
    
    exponential_expr =          //ADDED
            primary_expr
        >> *(exponential_op > unary_expr)
        ;
    
    primary_expr =
            uint_
        |   identifier
        |   bool_
        |   '(' > expr > ')'
        ;
    ...
    (additive_expr)
    (multiplicative_expr)
    (exponential_expr)      //ADDED //Line 150
    (exponential_operand)   //ADDED
    (unary_expr)
    ...
    
    ...
    case op_div:
        line += "      op_div";
        break;
    
    case op_exp:        //ADDED //Line 105
        line += "      op_exp";
        break;
    
    case op_eq:
        line += "      op_eq";
        break;
    ...
    case ast::op_times: program.op(op_mul); break;
    case ast::op_divide: program.op(op_div); break;
    case ast::op_exp: program.op(op_exp); break;  //ADDED //Line 244
    
    case ast::op_equal: program.op(op_eq); break;
    ...
    
    ...
    op_mul,         //  multiply top two stack entries
    op_div,         //  divide top two stack entries
    op_exp,         //ADDED //Line 24
    
    op_not,         //  boolean negate the top stack entry
    ...
    
    ...
    case op_div:
        --stack_ptr;
        stack_ptr[-1] /= stack_ptr[0];
        break;
    
    case op_exp:    //ADDED //Line 60
        --stack_ptr;
        stack_ptr[-1] = std::pow(stack_ptr[-1],stack_ptr[0]);
        break;
    
    case op_eq:
        --stack_ptr;
        stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
        break;
    ...