Bernard Hugueney | 1 Feb 08:37

[Spirit2] API ease of use vs. efficiency tradeoffs

Dear Spiriters,

I came to a better understanding of the Spirit2x API thanks to your messages and
a little investigation.

It appears to me that Spirit2(x) uses pass-by-reference "out" arguments and bool
return value instead of boost::optional<> for performance reasons. Also for
performance reasons, it uses default constructor and swap() (when using
rule<>::operator%=() ) instead of "copy" constructor.

(Hereafter, I'll consider that rule<> are used to create AST nodes, so rules
result type is for example ast_node, while parsed data would be for example int
float std::string, or boost::fusion::vector<> combinaison of those, the parsed
data would be of type parsed_data_t).

However, I would like to question those choices :

1) With regard to default constructor and swap() it create two constraints that
I consider bothersome :
a) AST nodes constructed from parsed data must be DefaultConstructible, with a
added state corresponding to "no parsed data".
b) AST nodes must be swappable with parsed data. The swap function cannot be
meaningful as soon as the AST node adds something to the parsed data, because
the parsed data cannot receive this info (-> "slicing"). Empiric evidence of the
uselessness of this functionality for custom AST is given by the fact that a
small bug in the Spirit2x implementation pervented to use custom swap function,
hence custom AST node types for rules using operator%=.

While these choice of API negatively impact the API of the client code with
"undue" constraints, I think (and am willing to investigate any benchmark
(Continue reading)

Joel de Guzman | 1 Feb 11:28
Picon
Favicon

Re: [Spirit2] API ease of use vs. efficiency tradeoffs

Bernard Hugueney wrote:
> Dear Spiriters,
> 
> I came to a better understanding of the Spirit2x API thanks to your messages and
> a little investigation.
> 
> It appears to me that Spirit2(x) uses pass-by-reference "out" arguments and bool
> return value instead of boost::optional<> for performance reasons. 

That's not the only reason. It also allows the client to pass in
an "unused" attribute, whereby removing the need to compute
attributes when it is not needed. It also allows the client
to pass in an attribute of some other type as long as it is
compatible with the parser's expected attribute (e.g. you can
pass in a std::string, a lightstring or a rope to +char_,
instead of the expected attribute of std::vector<char>. Both
are very important requirements that cannot be met when the
synthesized attribute is returned from the parse function.

> Also for
> performance reasons, it uses default constructor and swap() (when using
> rule<>::operator%=() ) instead of "copy" constructor.

That is another matter since it is implementation. It can be done
either way.

> (Hereafter, I'll consider that rule<> are used to create AST nodes, so rules
> result type is for example ast_node, while parsed data would be for example int
> float std::string, or boost::fusion::vector<> combinaison of those, the parsed
> data would be of type parsed_data_t).
(Continue reading)

Bernard Hugueney | 1 Feb 14:22

Re: [Spirit2] API ease of use vs. efficiency tradeoffs

Joel de Guzman <joel <at> boost-consulting.com> writes:

> > It appears to me that Spirit2(x) uses pass-by-reference "out" arguments
> > and bool
> > return value instead of boost::optional<> for performance reasons. 
> 
> That's not the only reason. It also allows the client to pass in
> an "unused" attribute, whereby removing the need to compute
> attributes when it is not needed.

In that case, I would believe that the value of the "unused" attribute is not
used, hence it could also be expressed using my proposed signature with
phrase_parse<unused_t>(begin, end, grammar, space).

> to pass in an attribute of some other type as long as it is
> compatible with the parser's expected attribute (e.g. you can
> pass in a std::string, a lightstring or a rope to +char_,
> instead of the expected attribute of std::vector<char>.

Indeed. I concur that this is a prefectly valid reason to pass by reference.

> I did agree with you that the DefaultConstructible requirement be abolished,
> didn't I?

Yes. I just wanted to restate this with the added requirment of swap() that
I discovered latter, as I believe the two issues are related.

> As for swap, no. Spirit, like STL, is more GP than OOP. It deals with
> concrete data types and ad-hoc polymorphism. I do not understand why
> you need to pass in an attribute that is a reference to a base type.
(Continue reading)

Joel de Guzman | 1 Feb 16:09
Picon
Favicon

Re: [Spirit2] API ease of use vs. efficiency tradeoffs

Bernard Hugueney wrote:
> Joel de Guzman <joel <at> boost-consulting.com> writes:
> 
>>> It appears to me that Spirit2(x) uses pass-by-reference "out" arguments
>>> and bool
>>> return value instead of boost::optional<> for performance reasons. 
>> That's not the only reason. It also allows the client to pass in
>> an "unused" attribute, whereby removing the need to compute
>> attributes when it is not needed.
> 
> In that case, I would believe that the value of the "unused" attribute is not
> used, hence it could also be expressed using my proposed signature with
> phrase_parse<unused_t>(begin, end, grammar, space).

Yep, but see below. I'll illustrate why.

>> to pass in an attribute of some other type as long as it is
>> compatible with the parser's expected attribute (e.g. you can
>> pass in a std::string, a lightstring or a rope to +char_,
>> instead of the expected attribute of std::vector<char>.
> 
> Indeed. I concur that this is a prefectly valid reason to pass by reference.

Yep. Generic programming allows this.

>> I did agree with you that the DefaultConstructible requirement be abolished,
>> didn't I?
> 
> Yes. I just wanted to restate this with the added requirment of swap() that
> I discovered latter, as I believe the two issues are related.
(Continue reading)

jono | 2 Feb 06:32

catching exceptions in Phoenix construct_


hi.

i have a parser that uses Phoenix to build an 'Object' based on input..

at the lowest level, there are a set of primitive object types, including 'Error'.  the one shown 
here, 'Time' is (among other things..) a boost::gregorian::date

the type 'Atom' is a boost::variant holding all the primitive types.

the type 'Object' is a shared pointer to Atom.

i have a bunch of parsers with semantic actions such as the following ...

///===========================================================

	int month, day, year;

///----------------------------------

	date_p = lexeme_d
		[
			uint2_p	[assign(day)] >> ch_p('/')
			>> months_p	[assign(month)] >> ch_p('/')
			>> uint4_p	[assign(year)]
		]
		;

///----------------------------------
	.
(Continue reading)

Bernard Hugueney | 2 Feb 07:43

Re: [Spirit2] API ease of use vs. efficiency tradeoffs

Joel de Guzman <joel <at> boost-consulting.com> writes:
> Bernard, your input is invaluable. I appreciate feedback like this.
> I *do* listen, you know. Your reasoning has merits and I would be
> amiss if I dismiss such valuable criticisms. I admire purity and
> idealism in code.

Thank you so much, I was not worried about your ability to listen but on my
ability to convey my point clearly. Kudos to you for being able to parse my
messages :-)

> > Thank you very much for your answer, and your work on Spirit2x
> 
> Most welcome. So here's my answer:
> 
> It would be good to first invite you to the spirit-devel list. I'd
> like to point you out to some threads I started as a means to self
> document the insides of Spirit2.

Most interesting reading ! I can't believe I used to consider parsers boring :-).

> Changing just
> the outermost function will merely give us a superficial
> solution. Believe me, this interface was considered before and
> the result of the current API was not taken lightly.

I do believe you : trust me, the idealistic coder in me has a very high opinion
of your libraries ;-).

> Having said that, it seems, based on my short experiment a day
> ago, that the return-attribute semantics *can* be simulated by
(Continue reading)

jono | 3 Feb 01:30

catching exceptions in Phoenix construct_ (cont...)


ie, i suppose what i mean is can i (easily) emulate the funtion of phoenix/statement.hpp try_ and 
catch_ in boost 1.33.1?

i have downloaded boost 1.37.0 but it may take me some time to port to it, and i'm looking for an 
interim solution...

cheers

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com
jono | 3 Feb 01:47

catching exceptions in Phoenix construct_ (ps:...)


as documented in...

boost_1_37_0/libs/spirit/phoenix/doc/html/phoenix/composite.html#phoenix.composite.statement

cheers.

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com
jono | 3 Feb 04:19

catching exceptions in Phoenix construct_ (pps:...)


ok, maybe i'm labouring under an illusion...

does phoenix try_/catch_ normally thrown exceptions in code called during evaluation of an actor, or 
only those originating from phoenix throw_ actors?

Jono

------------------------------------------------------------------------------
Create and Deploy Rich Internet Apps outside the browser with Adobe(R)AIR(TM)
software. With Adobe AIR, Ajax developers can use existing skills and code to
build responsive, highly engaging applications that combine the power of local
resources and data with the reach of the web. Download the Adobe AIR SDK and
Ajax docs to start building applications today-http://p.sf.net/sfu/adobe-com
jono | 3 Feb 04:29

catching exceptions in Phoenix construct_ (ppps:...)

hi

for example, should the attached code print anything (see below)?  and can i write this so it does?

also, could you point me to the docs explaining the significance of the 'spirit/home/phoenix' 
directory as it relates to Phoenix and Phoenix-2?

sorry about all the messages.

cheers
Jono

///==================================== code
#include <stdexcept>
#include <string>

#include <boost/spirit/home/phoenix/core.hpp>
#include <boost/spirit/home/phoenix/operator/self.hpp>
#include <boost/spirit/home/phoenix/statement.hpp>
#include <boost/spirit/home/phoenix/function/function.hpp>
#include <boost/detail/lightweight_test.hpp>

using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;

struct boom_impl
{
     template <typename Arg>
     struct result
     {
(Continue reading)


Gmane