Re: Feature wishlist for P::RD 2.0 ore perhaps 1.81

[email protected] (Damian Conway)
Newsgroups perl.recdescent
Message-ID <[email protected]>
Karl Gaissmaier wrote:

....some suggestions for additional features of Parse::RecDescent, specifically
the ability to specify "required alternatives" within a repeated subrule:

   > statement: A! | B! | C | D

and "mutually exclusive alternations":

   > rule     : A ^ B ^ C


The problem with these proposed features is that they are not *localized*.

That is, the presence of an A! doesn't affect the rule that the A! is in,
it affects the rule that calls the rule that the A! is in. And that is difficult
to implement in a recursive descent parser.


> But I think that P::RD is by far no way just a CFG ParserGenerator, it's a beast. 

<grin> I should quote you in the documentation. ;-)


> I stumbled so many times over these two missing features (mandatory and xor)
> and my "feeling" tells me, there must be a gentler(general) solution
> than just doing this in action codes.

Clearly this has been a problem for you. But I would have solved it like so:

	$grammar = << 'EOGRAMMAR';
    	contact   : statement(s)
						{ $return = { map %$_ @{$item[-1]} } }
                    <reject: do{!($return->{email} && $return->{name})) >
    	statement : email | name |  phone | fax
    	email     : 'email' '=' value  {{email=>$item[-1]}}
    	name      : 'name' '=' value   {{name=>$item[-1]}}
    	phone     : 'phone' '=' value  {{phone=>$item[-1]}}
    	fax       : 'fax' '=' value    {{fax=>$item[-1]}}
   	 value     : /".*?"/
	EOGRAMMAR

Since you needed to collect the data anyway, the actions would have had to be
there no matter what. So the overhead for the requirements testing is just the single
<reject> directive.

Likewise, if (for example) phone and fax were mutually exclusive, you could
just extend that to:

	$grammar = << 'EOGRAMMAR';
    	contact   : statement(s)
						{ $return = { map %$_ @{$item[-1]} } }
                    <reject: do{!($return->{email} && $return->{name})} >
                    <reject: do{  $return->{phone} && $return->{fax}  } >
    	statement : email | name |  phone | fax
    	email     : 'email' '=' value  {{email=>$item[-1]}}
    	name      : 'name' '=' value   {{name=>$item[-1]}}
    	phone     : 'phone' '=' value  {{phone=>$item[-1]}}
    	fax       : 'fax' '=' value    {{fax=>$item[-1]}}
   	 value     : /".*?"/
	EOGRAMMAR


> Perhaps Damian can bring some light in the darkness.

Perhaps. But I doubt it. ;-)

However, since you've taken the trouble to mention (and obviously think about) 
this problem, I will certainly devote some time to it myself and see if I can 
develop a better solution; one that's consistent with a recursive descent implementation.

Damian
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.