Phil Endecott | 2 Nov 15:22

Questions about longest_d

Dear Experts,

I have a couple of questions about longest_d in Spirit "classic":

Firstly, I tried to write
     longest_d[ a >> !b ]
which didn't work; it seems that I have to write
     longest_d[ a | (a>>b)]
which is a bit awkward when a is non-trivial.  Is there a way around this?

Secondly, I tried adding some actions:
     longest_d[ a[assign_a(foo,1)] | b[assign_a(foo,2)] ]
It looks as if both actions are always executed; in contrast, if I 
don't have the longest_d then the second action is only executed if a 
doesn't match.  I was hoping that some sort of no_actions_d  evaluation 
would be done here.  Is there a way that I can combine no_actions_d 
with longest_d here?

The problem that I'm actually trying to solve is something like this:

angle ::= decimal_degrees | degrees_minutes
decimal_degrees ::= real opt_degreeslabel
degrees_minutes ::= integer degreeslabel real minuteslabel
opt_degreeslabel ::= degreeslabel | nothing
degreeslabel ::= degrees | degs | deg | d | \262 | \302\260
minuteslabel ::= minutes | mins | min | m | '

Example inputs: "45 degrees", "45.45 degs", "45.45", "45", "45 degrees 
15 mins".

(Continue reading)

Joel de Guzman | 2 Nov 19:54
Picon
Favicon

Re: Questions about longest_d

Phil Endecott wrote:
> Dear Experts,
> 
> I have a couple of questions about longest_d in Spirit "classic":
> 
> Firstly, I tried to write
>      longest_d[ a >> !b ]
> which didn't work; it seems that I have to write
>      longest_d[ a | (a>>b)]
> which is a bit awkward when a is non-trivial.  Is there a way around this?

Sorry, no. longest_d works only on alternates.

> Secondly, I tried adding some actions:
>      longest_d[ a[assign_a(foo,1)] | b[assign_a(foo,2)] ]
> It looks as if both actions are always executed; in contrast, if I 
> don't have the longest_d then the second action is only executed if a 
> doesn't match.  I was hoping that some sort of no_actions_d  evaluation 
> would be done here.  Is there a way that I can combine no_actions_d 
> with longest_d here?

That's a basic problem with longest_d. There's no way to know which
one actually won. Both alternate paths are tried and if there are
actions attached in the alternate paths, they are executed.

> The problem that I'm actually trying to solve is something like this:
> 
> angle ::= decimal_degrees | degrees_minutes
> decimal_degrees ::= real opt_degreeslabel
> degrees_minutes ::= integer degreeslabel real minuteslabel
(Continue reading)

Joel de Guzman | 2 Nov 20:03
Picon
Favicon

Re: [Phoenix2] Lazy function

Thomas Taylor wrote:
> Still working on the grammar where a semantic action calls phrase_parse.
> To get the phrase_parse call working Joel pointed out that it needs to be
> lazy.
> 
> However I cannot work out how this implementation should look like.
> (Currently I am trying to do a lazy function, previous efforts of binding a
> corresponding member function have failed as well.)
> Here is my failing code:
> 
> // Phoenix lazy function, spirit parse call.
> struct lazy_subparse_impl
> {
>  template <typename parsedT> struct result { typedef parsedT type; };
>  template <typename parsedT> std::vector<GepNode> operator()(std::string&
>     SubScope, other& data) const;
> };

See: http://tinyurl.com/5rdz9l for the correct usage of the "result"
struct. Your usage is wrong because your operator() has 2 arguments
while your result template has only one. The result template should
reflect your arguments.

Regards,
--

-- 
Joel de Guzman
http://www.boostpro.com
http://spirit.sf.net

-------------------------------------------------------------------------
(Continue reading)

Picon
Gravatar

root_node_d: Lacking documentation

First of all, googling spirit terms seldom give hits pointing to the documentation... this is painful! Bad indexing?
 
 
I have just finished a rather complex grammar, and now I'm adding directives to make it "AST ready". Just like many times before, I do not get the full picture when reading through the docs. E.g. What happens in these scenarios?
 
1) Multiple root nodes. Do we need a new rule here? I would expect this type of example in the docs.
a = root_node_d[b] >> c >> (root_node_d[d] >> e);
 
With my current view, I would expect this tree:
Parent: b
Children: c, d where d has its own child: e
 
Correct?
 
2) A conditional root node. What happens if y is not matched?
x = root_node_d[!y] >> z;
 
3) Perhaps a stupid question, but does eps_p generate a node too? 
i = root_node[j] | eps_p; // Should "eps_p" be inside a root_node_d?
 
Thank you for your time!

Höststäda med nya dammsugarpåsar. www.Dammsugarpåsar.Nu
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Spirit-general mailing list
Spirit-general <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spirit-general
Felix Woller | 4 Nov 13:38
Picon

conditional parsing?

Hi,

i am new in spirit and was searching for a while on how to solve this problem without success.

The grammar i am working on is something like:

 

   rule_n =

      // Here I would like to have another_rule parsed only if problem_rule was called from main_rule (else only uint_p)

      ( uint_p | another_rule )

      ;

      

   // a lot of different rules rule_k ( k = 1,..,n-1 )

   // rule_k =

   //    >> ...

   //    >> rule_k+1

   //    >> ...

   //    ;

  

   rule_2 =

      // ...

      rule_3

      // ...

      ;

      

   rule_1 =

      // ...

      rule_2

      // ...

      ;

 

   problem_rule =

      // ...

      rule_1

      // ...

      ;

 

   main_rule =

      // ...

      problem_rule

      // ...

      ;

 

If problem_rule was called from main_rule, then i would like to have another_rule parsed.

First i was thinking about creating two versions of problem_rule. But for that i have to copy all of the rules rule_k.

Then i was thinking about using the if_p parser in rule_n but i don’t know how.

Can anyone help me to solve this without copying the rules rule_k?

 

best regards

Felix

 

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Spirit-general mailing list
Spirit-general <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spirit-general
Phil Endecott | 4 Nov 14:50

Re: Questions about longest_d

Hi Joel, thanks for replying.

Joel de Guzman wrote:
> Phil Endecott wrote:

>> Secondly, I tried adding some actions:
>>      longest_d[ a[assign_a(foo,1)] | b[assign_a(foo,2)] ]
>> It looks as if both actions are always executed; in contrast, if I 
>> don't have the longest_d then the second action is only executed if a 
>> doesn't match.  I was hoping that some sort of no_actions_d  evaluation 
>> would be done here.  Is there a way that I can combine no_actions_d 
>> with longest_d here?
>
> That's a basic problem with longest_d. There's no way to know which
> one actually won. Both alternate paths are tried and if there are
> actions attached in the alternate paths, they are executed.

Why can't it try both with no_actions_d[], and then having determined 
which has the longest match re-parse it with the actions enabled?

>> The problem that I'm actually trying to solve is something like this:
>> 
>> angle ::= decimal_degrees | degrees_minutes
>> decimal_degrees ::= real opt_degreeslabel
>> degrees_minutes ::= integer degreeslabel real minuteslabel
>> opt_degreeslabel ::= degreeslabel | nothing
>> degreeslabel ::= degrees | degs | deg | d | \262 | \302\260
>> minuteslabel ::= minutes | mins | min | m | '
>> 
>> Example inputs: "45 degrees", "45.45 degs", "45.45", "45", "45 degrees 
>> 15 mins".
>> 
>> I've ended up needing longest_d because (a) I want to consume the 
>> optional degreeslabel if it's present, even though it's not required; 
>> and (b) as with the example for longest_d in the docs, I want to parse 
>> the minutes if present rather than just consuming the integer degrees.
>> 
>> Any good solutions anyone?
>
> I think you just need to use the strict reals for parsing the real parts

Well, I've managed to simplify the grammar slightly differently to 
remove the need for longest_d.

My fundamental problem is that I have understood how yacc grammars work 
rather well for a couple of decades now, and when faced with a slightly 
different parser I find it hard to un-learn things.  Specifically it's 
the lack of backtracking in Spirit that catches me out, and I find 
myself doing convoluted things to work around it.  Even then, I worry 
that my grammar is subtly wrong (i.e. will fail to match something, or 
will loop forever at runtime).  Maybe I need to understand the theory 
better.  Any references?

Cheers,  Phil.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
Joel de Guzman | 5 Nov 00:54
Picon
Favicon

Re: Questions about longest_d

Phil Endecott wrote:

> Well, I've managed to simplify the grammar slightly differently to 
> remove the need for longest_d.
> 
> My fundamental problem is that I have understood how yacc grammars work 
> rather well for a couple of decades now, and when faced with a slightly 
> different parser I find it hard to un-learn things.  Specifically it's 
> the lack of backtracking in Spirit that catches me out, and I find 
> myself doing convoluted things to work around it.  Even then, I worry 
> that my grammar is subtly wrong (i.e. will fail to match something, or 
> will loop forever at runtime).  Maybe I need to understand the theory 
> better.  Any references?

Sure: http://en.wikipedia.org/wiki/Parsing_expression_grammar

I learned after Spirit1 that it is not really BNF, but PEG, Spirit
implements.

Also, Spirit is top-down, instead of bottom-up like YACC. That is
also another source of confusion. Quoting (http://tinyurl.com/es3qg):

"There is contention between the "European school" of language
design, who prefer LL-based grammars, and the "US-school", who
predominantly prefer LR-based grammars.[citation needed] This is
largely due to teaching traditions and the detailed description of
specific methods and tools in certain text books; another influence
may be Niklaus Wirth at ETH Zürich in Switzerland, whose research
has described a number of ways of optimising LL(1) languages and
compilers."

I've had the same observation. I learned Parsing from Pascal and
used ANTLR before YACC. So, there's where my bias lies.

Regards,
--

-- 
Joel de Guzman
http://www.boostpro.com
http://spirit.sf.net

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
Michael Weber | 5 Nov 23:10

parser compiled with msvc9 is four to five times slower relative to msvc8

Hello,


1. It appears that msvc 8 generates faster Spirit Classic code than msvc 9.

Earlier this year I used Spirit 1.8.4 / Boost 1.34.1 to implement a cross-platform cascading style sheet parser (and had fun doing it, I might add -- great framework!). Recently I switched to Boost 1.36 in order to use Visual Studio 2008 for the Windows target (msvc compiler v9), keeping the implementation based on what is now called Spirit Classic. Unfortunately, the performance of the Spirit Classic parser is four to five times times slower when compiled with msvc9, using the same compiler settings ("full optimization" in IDE). I experimented with a few different optimization settings to no avail. The performance impact is only on code that uses Spirit -- not other portions. It compiles / links faster with msvc9, but runs slower.

I am posting to ask if any others have had a similar experience with msvc8 vs. msvc9. Is this known issue? Did anyone get around it? (I searched the archives first but did not find posts about this problem). 

2. I investigated another approach to making the parser faster, by pushing my rules into parser types. To convert my grammar's rule member objects into parser member objects, I of course need to use the "compiler error trick". For CSS, the rules grow complicated enough that eventually the compiler goes into never-never land and the compiler error trick is impractical. I managed to get the parser-equivalents for a significant set of low-level rules. But then when I compile the remaining rules (which now invoke parsers rather than rules), the msvc runs out of heap space, after using around 1.5 Gb. Therefore, I think my original grammar design was reasonable, since it does compile and run.

3. Is there an example of how to generate parse trees tagged with rule IDs in Spirit 2, with tree nodes containing begin / end iterators to matched ranges in the input string?

Scanning the mailing list, I am hopeful that Spirit 2 will be the way to go for the future. However, the documentation / examples are still a little sparse. My current CSS parser generates a parse tree where each node is tagged with a rule ID and iterators into the input buffer. The Spirit 2 documentation for these topics looks like placeholders for unwritten content (unless I am missing files). I also cannot find an demonstrating how to generate an equivalent parse tree with Spirit 2, but perhaps I do not understand the examples.

thanks in advance for any tips,
Michael Weber
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Spirit-general mailing list
Spirit-general <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spirit-general
Carl Barron | 6 Nov 02:51

Re: parser compiled with msvc9 is four to five times slower relative to msvc8


On Nov 5, 2008, at 5:10 PM, Michael Weber wrote:

> Hello,
> [smp msvc stuff , don't use it:)]

> 3. Is there an example of how to generate parse trees tagged with  
> rule IDs in Spirit 2, with tree nodes containing begin / end  
> iterators to matched ranges in the input string?.

>
> Scanning the mailing list, I am hopeful that Spirit 2 will be the  
> way to go for the future. However, the documentation / examples are  
> still a little sparse. My current CSS parser generates a parse tree  
> where each node is tagged with a rule ID and iterators into the  
> input buffer. The Spirit 2 documentation for these topics looks like  
> placeholders for unwritten content (unless I am missing files). I  
> also cannot find an demonstrating how to generate an equivalent  
> parse tree with Spirit 2, but perhaps I do not understand the  
> examples.
>

There are no built in trees or rule ids in spirit 2.  You have  
complete control of what a parser creates as a 'return'   There are no  
closures
only local variables, inherited_variables ,  It makes writing grammars  
and their action actually much simpler and execute much faster as
welll.   That said  the purpose of rule-ids was to identifiy what type  
of node you have, so a separate type for each different node  type  
serves
the purpose.

Examplle   a simple four function calculator of doubles requires  five  
different nodes 4 of which are essetially the same and one
holds a double   so

	template <char C>   struct binary_node;	

	typedef boost ::variant
	<
		double,
		boost::recursive_wrapper<binary_node<'+'> >,
		boost::recursive_wrapper<binary_node<;'-'> >,
		boost::recursive_wrapper<binary_node<'*'> >,
		boost::recursive_wrapper<binary_node<'/'> >
	>	expr_node;

	template <char C>  struct make_op;

	template <> struct make_op<'+'> {typedef std::plus<double> type;};
	template <> struct make_op<'-'> { typedef std::minus<double> type;};
	etc.

	template <char C>
	struct binary_node
	{
		expr_node left,right;
		binary_node(const expr_node &a,const expr_node &b)
			:left(a),right(b);
	};

	defines an ast for a an expression.   evaluation is simply a functor  
with overloaded operator ()'s.

	struct evaluate:boost::static_visiitor<double>
	{
		double operator () (double x) const { return x;}
		template <char C>o operator () ( const binary_node<C> & x) const
		{
			typename make_op<C>::type operation;
			return  operation( evaluate(left), evaluate(right));
		}
	};

	now the grammar is simply

	expr_node & operator += ( expr_node &left ,const expr_node &left)
	{
		return left =  binary_node<'+'>(left,right);
	}

	// etc for op -= ,*=,/=

	template <class Iter>
	struct expression_gram:grammar
	<
		Iter,	// the iterator
		expr_node(),	//  signature   synthetic attribute node and no  
inherited_attributes,
		space_type	//  skipper type
	>
	{
		expression_gram():expr_gram::base_type(expr)	// expr is the start rule
		{
			expr =   term [_val = _1]
				>> *(   '+' >> term [ _val += _1]
					|  '-' >> term [ _val -= _1]
					)
				;
			term =  factor [_val = _1]
				>> *(  '*' >> factor [_val *= _1]
					|  '/' >> factor [_val /= _1]
					)
				;
			factor = doiuble_ [[_val = _1]
				| '('  expr [_val = _1]  >> ')'
				;
		}
		typedef rule<Iter,expr_node(),space_type>	rule_t;
		rule_t expr,term,factor;
	};

	generates the tree

	int main()
	{
		std::string data("1 + 2");
		typedef std::string::iterator iterator;
		iterator first(data.begin();
		expression_grammar<iterator>  gram;
		expr_node   tree;
		bool r = phrase_parse(first,data.end(),gram,tree,space);
		if(r)
		{
			std::cout << "result is " << apply_visitor(evalujate(),tree) << '\n';
		}
		else
		{
			std::cout << "Parse failed\n";
		}
	}
	
	notice how much cleaner this is!!

I hope this fills in some 'spaces' left by the docs.   The same  
approach can probably be used for CSS allthough the actual types
are different and the grammar is different.   There are other changes  
in grammars from spirit 1 like names of primittives,,,

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
Picon
Gravatar

Spirit v2: Left recursion elimination?

Does Spirit v2 suffer from the "Left recursion" problem present in Spirit v1?
Beställ bläck före 19 för leverans nästa vardag inkClub
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Spirit-general mailing list
Spirit-general <at> lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spirit-general

Gmane