boost-spirit 数字解析器并获取所需的合成属性

发布于 2024-10-30 21:15:44 字数 1305 浏览 4 评论 0原文

--编辑--解决了问题:对最后一个旁注的评论会很有帮助。另外,对 phoenix::bind 重载处理的评论也会有所帮助(在我的回答中)。

我正在一个具有严格类型要求的系统上工作,我想确保我正在解析满足 int32_t 和约束的整数int64_t,我不希望解析器将解析的字符串综合并限制为上述类型。

我该怎么办? 文档< /a> 提到 long_long 仅在支持 64 位的平台上可用,但我也需要在 32 位平台上解析 int64_t。

我的解析器的摘录如下:

...
  eps(_b == VALUE_INT4) >> qi::long_ 
    [phoenix::bind(&AddEntry, _r1,_a, _1, _pass)] ) // 
| ( eps(_b == VALUE_INT8) >> qi::long_long)
...

AddEntry 有一个 int32_t 重载和一个 int64_t 重载,是一个 phoenix::static_cast__1按顺序?如果是这种情况,如何在现代 32 位平台上解析 64 位整数?我假设 BOOST_HAS_LONG_LONG 仅在过时的硬件上未定义,例如 8008 ;)。

<咆哮> 我希望他们坚持 c99 和 中规定的标准,我们大多数人都希望针对干净的抽象进行编程。以这种方式定义数字解析器可能有充分的理由。然而,大计划的使用可以在文档中更好地定义。

旁注:上面的条件 epsilon 样式在性能上是否可以与 case 语句相媲美?

--edit -- Solved the question : a comment on the last sidenote would be helpfull. Also comments on phoenix::bind overload handling would be helpfull (in my answer).

I'm working on a system with strict typing requirements, I want to ensure that I am parsing integers that meet the constraints of int32_t and int64_t, I wan't the parsers to synthesise and constrain the parsed strings to the mentioned types.

How do I go about this ? The document mentions that long_long is only available on platforms with 64-bit support, but I need to parse int64_t's on 32-bit platforms as well.

An excerpt from my parser is as follows:

...
  eps(_b == VALUE_INT4) >> qi::long_ 
    [phoenix::bind(&AddEntry, _r1,_a, _1, _pass)] ) // 
| ( eps(_b == VALUE_INT8) >> qi::long_long)
...

AddEntry has a int32_t overload and a int64_t overload, is a phoenix::static_cast_ on _1in order ? And if this is the case how do I parse 64-bit integers on a modern 32-bit platform ? I assume BOOST_HAS_LONG_LONG is only not-defined on archaic hardware like the 8008 ;) .

<Rant>
I wish they had stuck with the standards set out in c99 and <boost/cstdint.hpp>, most of us want to program against clean abstractions. There are probably good reasons for the numeric parsers being defined the way they are. however, grand-scheme use could be better defined in the documentation.
</Rant>

On a side note: Does the conditional epsilon style above rival a case statement in performance ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ˉ厌 2024-11-06 21:15:44

1) Qi 解析器已经检查溢出情况。如果输入不能用组件应该匹配的类型表示,则解析器组件将失败。例如,对于不适合有符号 32 位整数的数字,int_parser 将失败。

仅当定义了 BOOST_HAS_LONG_LONG 时,才可以使用 long_long 解析器(即预定义的 64 位整数解析器)。如果您的平台并非如此,您仍然可以通过编写自己的包装器类型来模拟 64 位整数,从而公开 Qi 数字解析器所期望的功能(请参阅 此处 ),例如:

struct my_64bit_int {
    //...
};
typedef int_parser<my_64bit_int, 10> my_64bit_int_parser_type;
my_64bit_int_parser_type const my_64bit_int_parser;

并将其用作:

my_64bit_int bigint;
parse(b, e, my_64bit_int_parser, bigint);

2) 如果不帮助编译器,则无法绑定重载函数,即:

void AddEntry(int32_t);
void AddEntry(int64_t);

如果要绑定 int32_t,则需要显式转换函数指针:

phoenix::bind((void(*)(int32_t))&AddEntry, _1);

对旁注的回答:否。替代解析器始终按照指定的相同顺序顺序执行不同的替代方案,当第一个匹配时停止。其总体复杂度为 O(N),其中 N 是单独替代方案的数量(请参阅 此处)。

1) Qi parsers already check for overflow conditions. The parser component will fail if the input is not representable by the type the component is supposed to match. For instance, int_parser<int32_t, 10> will fail for numbers not fitting into a signed 32 bit integer.

You can use the long_long parser (i.e. the predefined 64 bit integer parser) only if BOOST_HAS_LONG_LONG is defined. If you have a platform where this is not the case, you can still emulate a 64bit integer by writing your own wrapper type exposing the functionality as expected by Qi numeric parsers (see here), for instance:

struct my_64bit_int {
    //...
};
typedef int_parser<my_64bit_int, 10> my_64bit_int_parser_type;
my_64bit_int_parser_type const my_64bit_int_parser;

and use it as:

my_64bit_int bigint;
parse(b, e, my_64bit_int_parser, bigint);

2) You can't bind overloaded functions without helping the compiler, i.e. given:

void AddEntry(int32_t);
void AddEntry(int64_t);

you need to cast the function pointer explicitly if you want to bind for an int32_t:

phoenix::bind((void(*)(int32_t))&AddEntry, _1);

Answer to sidenote: No. The alternative parser is always sequentially executing the different alternatives in the same sequence as specified, stopping when the first of those matches. Its overall complexity is O(N), where N is the number of separate alternatives (see here).

夜空下最亮的亮点 2024-11-06 21:15:44

这些模板将为您提供您想要的语义。

qi::int_parser< int32_t,  10, 1,10>  p_int32_t;
qi::int_parser< int64_t, 10, 1, 19> p_int64_t;

这些解析器经过了单元测试,并在溢出时产生了期望错误,即分别在 >= 2^31>= 2^63 时。

phoenix::bind afaik 不会拾取重载(如果我错了,请纠正我),

的宏如下

#define  ADD_ENTRY(TP,prefix)                                           \
    void AddEntry_##prefix( value_variant_vector & v, uint32_t ordinal, \
                            TP entry, bool & ok_)                       \

因此,对于那些感兴趣的人,编译器错误消息 (当 AddEntry是一个模板函数):

/opt/dev_64_swat/dsl/src/parser/RowAndTable.cc:43: error: no matching function 
for call to ‘bind(<unresolved overloaded function type>, const
boost::phoenix::actor<boost::spirit::attribute<1> >&, const 
boost::phoenix::actor<boost::spirit::local_variable<0> >&, const 
boost::phoenix::actor<boost::spirit::argument<0> >&, const   
boost::phoenix::actor<boost::phoenix::argument<2> >&)’

我也遇到手写重载错误。

These templatas will get you the semantics you want.

qi::int_parser< int32_t,  10, 1,10>  p_int32_t;
qi::int_parser< int64_t, 10, 1, 19> p_int64_t;

These parsers were unit tested and created expectation errors on overflow --i.e., when >= 2^31 and >= 2^63 respectively.

Overloads aren't picked up by phoenix::bind afaik (correct me if I'm wrong please),

therefore a macro along the lines of

#define  ADD_ENTRY(TP,prefix)                                           \
    void AddEntry_##prefix( value_variant_vector & v, uint32_t ordinal, \
                            TP entry, bool & ok_)                       \

For those interested the compiler error message is as follows (when AddEntry is a template function):

/opt/dev_64_swat/dsl/src/parser/RowAndTable.cc:43: error: no matching function 
for call to ‘bind(<unresolved overloaded function type>, const
boost::phoenix::actor<boost::spirit::attribute<1> >&, const 
boost::phoenix::actor<boost::spirit::local_variable<0> >&, const 
boost::phoenix::actor<boost::spirit::argument<0> >&, const   
boost::phoenix::actor<boost::phoenix::argument<2> >&)’

I get errors on hand written overloads as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文