Re: binary shifts in p::rd exe block
[email protected] ("Ron D. Smith") Tue, 10 Jun 2003 16:35:18 -0700
| Newsgroups | perl.recdescent |
|---|---|
| Message-ID | <[email protected]> |
On Monday, Jun 9, 2003 "h. w. neff" said:
> ok, i now have a much pared down example that exhibits the
> problem -- at least with attempts to use '<<' in an exe
> block.
<blessedly snipped>
Wow. If that was "pared down" I would hate to see "the whole script" :-)
This one is kind of subtle, and reminds me of the quote "nothing can parse
perl except perl".
The problem is in Text::Balanced::_match_quotelike where it thinks the '<<'
is a hereis operator instead of a shift and tries to process it like a
quoting operator. Since nothing follows the '<<' that really corresponds to
a label, it looks for "" instead. See Text::Balanced::_match_quotelike
starting at line 714:
if ($op eq '<<') {
$ld1pos = pos($$textref);
my $label;
if ($$textref =~ m{\G([A-Za-z_]\w*)}gc) {
$label = $1;
}
elsif ($$textref =~ m{ \G ' ([^'\\]* (?:\\.[^'\\]*)*) '
| \G " ([^"\\]* (?:\\.[^"\\]*)*) "
| \G ` ([^`\\]* (?:\\.[^`\\]*)*) `
}gcx) {
$label = $+;
}
else {
$label = "";
}
What happens is that $label is being set to null so the quote terminator is
looking for a BLANK LINE.
Here is a much simpler test case which fails.
use Parse::RecDescent;
use Data::Dumper;
$::RD_ERRORS = 1; # Make sure the parser dies when it encounters an error
$::RD_WARN = 1; # Enable warnings. This will warn on unused rules &c.
$::RD_HINT = 1; # Give out hints to help fix problems.
$::RD_TRACE=100;
$mach_grammar = q
{
acu_config_cmd :
';'
{
$main::Instruction_lower = 0x000000
| (($item[16] & 0x000003)<<10)
;
1;
}
};
my $mach_parser = new Parse::RecDescent ($mach_grammar);
Where it outputs the following:
Parse::RecDescent: Treating "acu_config_cmd :" as a rule declaration
Parse::RecDescent: Treating ";" as a literal terminal
printing code (3612) to RD_TRACE
But this works:
use Parse::RecDescent;
use Data::Dumper;
$::RD_ERRORS = 1; # Make sure the parser dies when it encounters an error
$::RD_WARN = 1; # Enable warnings. This will warn on unused rules &c.
$::RD_HINT = 1; # Give out hints to help fix problems.
$::RD_TRACE=100;
$mach_grammar = q
{
acu_config_cmd :
';'
{
$main::Instruction_lower = 0x000000
| (($item[16] & 0x000003)<<10)
;
1;
}
};
my $mach_parser = new Parse::RecDescent ($mach_grammar);
Now PAY ATTENTION: The only difference between the two cases is the *BLANK*
line after the expression with the '<<' in it!!!!
Yet this works and correctly picks up the action:
Parse::RecDescent: Treating "acu_config_cmd :" as a rule declaration
Parse::RecDescent: Treating ";" as a literal terminal
Parse::RecDescent: Treating "{ $main::Instruction_lower = 0x000000 |
(($item[16] & 0x000003)<<10) ; 1; }" as an action
printing code (4229) to RD_TRACE
The reason for the bug is that it consumes the entire input and the parser
fails in a bizarre way that makes it think everything after the '<<' is part
of that hereis literal.
So to fake it out, give it what it wants, which is a blank line after every
usage of the '<<' shift operator, but you have to do it INSIDE the action.
The original code had the blank line after the action and the parser parser
looses it mind.
So with your original code, change it to this:
acu_config_cmd :
bus0_p_see_clause
{
$main::LastSuccess = "a bus0 'ptr see clause'";
$main::LookingFor = "a comma and a bus0 'update clause'";
}
bus0_update_clause
{
$main::LastSuccess = "a bus0 'update clause'";
$main::LookingFor = "a comma'";
}
','
{
$main::LastSuccess = "a comma";
$main::LookingFor = "a bus1 'ptr see clause'";
}
bus1_p_see_clause <commit>
{
$main::LastSuccess = "a bus1 'ptr see clause'";
$main::LookingFor = "a comma and a bus1 'update clause'";
}
bus1_update_clause
{
$main::LastSuccess = "a bus1 'update clause'";
$main::LookingFor = "a comma'";
}
','
{
$main::LastSuccess = "a comma";
$main::LookingFor = "a bus2 'ptr see clause'";
}
bus2_p_see_clause
{
$main::LastSuccess = "a bus2 'ptr see clause'";
$main::LookingFor = "a comma and a bus2 'update clause'";
}
bus2_update_clause
{
$main::LastSuccess = "a bus2 'update clause'";
$main::LookingFor = "a comma'";
}
','
{
$main::LastSuccess = "a comma";
$main::LookingFor = "a bus3 'ptr see clause'";
}
bus3_p_see_clause
{
$main::LastSuccess = "a bus3 'ptr see clause'";
$main::LookingFor = "a comma and a bus3 'update clause'";
}
bus3_update_clause
{
$main::LastSuccess = "a bus3 'update clause'";
$main::LookingFor = "a comma'";
}
','
{
$main::LastSuccess = "a comma";
$main::LookingFor = "a sm_b0123 'see clause'";
}
sm_b0123_see_clause
{
$main::LastSuccess = "a sm_b0123 'see clause'";
$main::LookingFor = "a semicolon";
}
';'
{
$main::Instruction_upper = 0x400000
| ($item[1] / 16)
| ($item[7] / 2)
| ($item[14] / 512)
| ($item[20] / 64)
| ($item[26] & 0x00000F)
;
$main::Instruction_lower = 0x000000
| ($item[3] / 2048)
| ($item[10] / 128)
| (($item[16] & 0xC00000) / 16384)
# | (($item[16] & 0x000003) * 1024)
| (($item[16] & 0x000003) << 10)
| (($item[22] & 0xC00000) / 1024)
| (($item[22] & 0x000003) * 16384)
| ($item[26] & 0xFF0000)
;# the next blank line is required.
1;
}
Yep, its just PFM.
--
Intel, Corp.
5000 W. Chandler Blvd.
Chandler, AZ 85226
--
Intel, Corp.
5000 W. Chandler Blvd.
Chandler, AZ 85226