为什么 Spirit 不抛出 qi::expectation_failure 而只是用未解析的左值解析 ok?

问题描述 投票:0回答:1

我(故意)遗漏了真正的单元测试和语法推导;)

看起来只有当 Spirit 已经检测到规则适用(从一开始)时,Excpetations 才相关,否则解析将会失败

它是一个简单的 C-Identifier 规则和一个 Identfier:Identifier 规则,跳过空格以显示我的误解

Coliru 直播

// #define BOOST_SPIRIT_DEBUG
#include <boost/fusion/include/io.hpp>
#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;

namespace Ast
{
    struct Identifier : std::string
    {
    };

    struct A_B
    {
        Identifier a;
        Identifier b;
    };
} // namespace Ast

BOOST_FUSION_ADAPT_STRUCT( Ast::A_B, a, b )

using Iter = std::string_view::const_iterator;

template <typename ValueType, typename RuleType>
void printing_parse_test( const RuleType& rule_, const std::vector<std::string>& tests )
{
    for( std::string_view test : tests )
    {
        try
        {
            std::cout << "Parsing: '" << test << "'\n";
            Iter f = test.begin(), l = test.end();
            // ">> qi::omit[*qi::space]" at end to eat in-between rest spaces ...
            ValueType v;
            const bool ok = qi::parse( f, l, rule_ >> qi::omit[*qi::space], v );
            std::cout << "parse-result: " << ( ok ? "ok" : "failed" ) << "\n";
            const std::string left( f, l );
            if( ok )
            {
                if( !left.empty() )
                {
                    std::cout << "FAIL: parsed someway but left this '" << left << "'\n ";
                }
                else
                {
                    std::cout << "OK: all parsed\n";
                }
            }
            else
            {
                if( !left.empty() )
                {
                    std::cout << "FAIL: parse failed left this: '" << left << "'\n";
                }
            }
        }
        catch( qi::expectation_failure<Iter> const& ef )
        {
            auto f = begin( test );
            auto p = ef.first - test.begin();
            auto bol = test.find_last_of( "\r\n", p ) + 1;
            auto line = std::count( f, f + bol, '\n' ) + 1;
            auto eol = test.find_first_of( "\r\n", p );

            std::cout << " -> EXPECTED " << ef.what_ << " in line:" << line << " col:" << ( p - bol ) << "\n"
                      << test.substr( bol, eol - bol ) << "\n"
                      << std::setw( p - bol ) << ""
                      << "^--- here" << std::endl;
        }
        std::cout << "--------------------\n";
    }
    std::cout << "============\n";
}

int main()
{
    qi::rule<Iter, Ast::Identifier()> identifier_rule = qi::char_( "a-zA-Z_" ) > *qi::char_( "a-zA-Z0-9_" );
    identifier_rule.name( "identifier_rule" );
    printing_parse_test<Ast::Identifier>( identifier_rule, { "  test blib ", "", "23434", "a$", "test blub" } );

    qi::rule<Iter, Ast::A_B()> A_B_rule = qi::skip( qi::space )[( identifier_rule > ":" > identifier_rule )];
    A_B_rule.name( "A_B_rule" );
    printing_parse_test<Ast::A_B>( A_B_rule, { "e$:bd", "a", "", "23434", "a$", "a:$" } );

    return 0;
}

输出:

Parsing: '  test blib '
parse-result: failed
FAIL: parse failed left this: '  test blib '
--------------------
Parsing: ''
parse-result: failed
--------------------
Parsing: '23434'
parse-result: failed
FAIL: parse failed left this: '23434'
--------------------
Parsing: 'a$'
parse-result: ok
FAIL: parsed someway but left this '$'
 --------------------
Parsing: 'test blub'
parse-result: ok
FAIL: parsed someway but left this 'blub'
 --------------------
============
Parsing: 'e$:bd'
 -> EXPECTED ":" in line:1 col:1
e$:bd
 ^--- here
--------------------
Parsing: 'a'
 -> EXPECTED ":" in line:1 col:1
a
 ^--- here
--------------------
Parsing: ''
parse-result: failed
--------------------
Parsing: '23434'
parse-result: failed
FAIL: parse failed left this: '23434'
--------------------
Parsing: 'a$'
 -> EXPECTED ":" in line:1 col:1
a$
 ^--- here
--------------------
Parsing: 'a:$'
 -> EXPECTED <identifier_rule> in line:1 col:2
a:$
  ^--- here
--------------------
============

期望:

为什么在使用这两个规则解析“23434”或空字符串等时我没有得到预期的? 我期望字符串不是以标识符开头吗?我怎样才能存档它 还是稍后组合我的规则时会出现问题?

还有一个问题是,为什么“a$”只产生预期的“:”,而不是标识符文字也可以的附加信息(或者这更像是一个提示?)

c++ boost-spirit
1个回答
0
投票

找到了

qi::eps

就是答案 - 这样我从一开始就得到了预期的序列

const bool ok = qi::parse( f, l, qi::eps > rule_ >> qi::omit[*qi::space], v );

在启动时也给我执行

© www.soinside.com 2019 - 2024. All rights reserved.