开发者

boost-spirit numeric parsers and getting the desired synthesised attributes

--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 workin开发者_运维知识库g 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 ?


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).


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜