c++ - qi::phrase_parse 返回真,即使调用了 qi::on_error

标签 c++ parsing boost boost-spirit

 bool EqnExprEvaluator::SetEqn(const std::string& eqnStr) {
     typedef std::string::const_iterator iterator_type;

     EquationExpr<iterator_type> eqnExpr;

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

     bool result;
     try {
         result = qi::phrase_parse(iter, iterEnd, eqnExpr, boost::spirit::ascii::space, *m_expressionAST);
         std::cout << "777777777777 ok, result = " << result << std::endl;
     }
     catch (const std::exception &e) {

         throw e;
     }
     catch (...) {
         throw std::runtime_error("Parser error");
     }

     return result;
 }


///////////////////////////////////////////////////////////////////////////
//  Equation grammar
///////////////////////////////////////////////////////////////////////////
template <typename Iterator>
    struct EquationExpr : qi::grammar<Iterator, ExpressionAST(),  ascii::space_type>
{
    static ExpressionAST make_binary_op(char op, const ExpressionAST &left,
            const ExpressionAST &right)  {

        ExpressionAST ast;
        ast.expr = binary_op(op,left,right);
        return ast;
    };
    //
    // Typedefs to make the code less verbose
    //
    typedef qi::rule<Iterator, std::string(), ascii::space_type> RuleString;
    typedef qi::rule<Iterator, ExpressionAST(), ascii::space_type> RuleAst;
    typedef qi::rule<Iterator, ExpressionAST(),
            qi::locals<ExpressionAST>,
            ascii::space_type>  RuleAstLocalVar;

    EquationExpr() : EquationExpr::base_type(expression_root,"equation") {
        boost::phoenix::function<negate_expr> neg;
        boost::phoenix::function<sqrt_expr> sqrtfunc;


        using qi::_val;
        using qi::_1;
        using qi::_2;
        using qi::_3;
        using qi::_4;
        using qi::double_;
        using qi::lit;
        using qi::_a;
        using qi::_pass;
        using qi::char_;
        using qi::string;
        using qi::alpha;
        using qi::alnum;
        using boost::phoenix::val;

        std::string varName;
        pow = lit("pow") > '(' >>  expression [_a = _1 ]
            > lit(",")
            > expression [_val = boost::phoenix::bind(make_binary_op,'^', _a,_1)]
            > ')'
            ;

        sqrt= lit("sqrt") > '(' >
            expression [_val = sqrtfunc(_1)]
            >> ')'
            ;

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

        term =
            factor              [_val = _1]
            >> *(   ('*' >> factor          [_val *= _1])
                    |   ('/' >> factor          [_val /= _1])
                )
            ;

        allowed_variable = '@' >
            (
             string("length") [_val = _1]
             | string("width") [_val = _1]
             | string("temperature") [_val = _1]
             | string("deltaT") [_val = _1]
            )
            ;
        illegal_variable = ! lit('@') >  alpha  > *alnum  [_val = _1 ] > !qi::eps [_pass]
            ;
        badPow = lit("pow") >> '(' >>  expression >> !lit(",") [_pass]
            ;
        factor =
            double_                         [_val = _1]
            | allowed_variable              [_val = _1]
            | pow                           [_val = _1]
            | sqrt                          [_val = _1]
            |   '(' >> expression           [_val = _1] >> ')'
            |   ('-' >> factor              [_val = neg(_1)])
            |   ('+' >> factor              [_val = _1])
            | badPow
            | illegal_variable              [_val = _1]
            ;

        //
        //  Naming the rules
        //
        pow.name("pow");
        sqrt.name("sqrt");
        expression_root.name("expression");
        term.name("term");
        allowed_variable.name("allowed_variable");
        factor.name("factor");

        //
        // Error handler
        //

        qi::on_error<qi::fail>
            (
             expression_root,
             std::cout << val("Error equation equation ")
             << boost::phoenix::construct<std::string>(_1,_2)
             << val ("\n")
            );
        qi::on_error<qi::fail>
            (
             badPow,
             std::cout << val("Error parsing function 'pow'.  Didn't find second argument ")
             << boost::phoenix::construct<std::string>(_1,_2)
             << val ("\n")
            );
        qi::on_error<qi::fail>
            (
             pow,
             std::cout << val("Error parsing function 'pow'  ")
             << boost::phoenix::construct<std::string>(_1,_2)
             << val ("\n")
            );

        qi::on_error<qi::fail>
            (
             allowed_variable,
             std::cout << val("Error parsing allowed variables  ")
             << val ("'\n")
             << val (" Allowed at @length, @width , @temperature, and @deltaT")
             << val ("'\n")
            );

        qi::on_error<qi::fail>
            (
             illegal_variable,
             std::cout << val("Error parsing variable   ")
             << val (" here: Got an illegal variable '")
             << "Arg " << boost::phoenix::construct<std::string>(_1,_2) << "'" << std::endl
             << "Arg4 " << _4 << std::endl 
             << boost::phoenix::construct<std::string>(_3,_2)
             << val ("'\n")
             << val (" Allowed at @length, @width , @temperature and @deltaT")
             << val ("'\n")
            );

    }

    RuleAst expression, term, factor,sqrt, expression_root;
    RuleString allowed_variable,illegal_variable;
    RuleAstLocalVar pow, badPow;
};

对于这个语法,打印错误信息qi::on_error<qi::fail> (illegal_variable,... , 但 phrase_parse 返回 true .谁能解释一下这怎么可能?

错误打印没问题,但phrase_parse 不应该返回false对于那种情况?

最佳答案

on_error 处理程序定义了您要执行的操作。

您想在操作中设置 qi::_pass = false

参见例如how to make error handling work for boost::spirit举个例子。

关于c++ - qi::phrase_parse 返回真,即使调用了 qi::on_error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35089696/

相关文章:

c++ - 在 3D 中 boost 两条线段的交集

c++ - 将 json 对象转换为字符串 boost

c++ - QSslCertificate 如何获取 Windows 中显示的公钥

Python:使用 mplayer 解析流标题

c++ - 仅在 boost::program_options 中的短选项

java - 为什么这个简单的 jparsec 词法分析器会失败?

parsing - 以双引号开头和结尾的标记的 Backus-Naur 形式

c++ - 访问指针指向的值

javascript - 用于在网页中注入(inject) javascript 的 IE 扩展

c++ - 这段代码是如何工作的?