即使调用qi :: on_error,qi :: phrase_parse也会返回true

时间:2016-01-29 16:43:27

标签: 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吗?

1 个答案:

答案 0 :(得分:0)

on_error处理程序定义了你想要完成的任务。

您想在操作中设置public class QuestionsWithPairedAnswers { [Key] public int? QuestionID { get; set; } public string vchQuestionText { get; set; } public string vchTextElementOneHeader { get; set; } public string vchTextElementTwoHeader { get; set; } public List<PairedAnswerTypes> Answers { get; set; } } public class PairedAnswerTypes { public int PairedTextElementAnswerID { get; set; } public int? QuestionID { get; set; } public int ContractorID { get; set; } public string vchTextElementOne { get; set; } public string vchTextElementTwo { get; set; } public virtual QuestionsWithPairedAnswers Question { get; set; } }

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