How to ignore newline in Parse::RecDescent

F

freesoft12

Hi,

I am new to Parse::RecDescent and I came across this problem of the
parser not being able to ignore the newline character. Is there a way
I can ask the parser to ignore all newlines?

Regards
John


### parser_test.pl ###
eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' && eval 'exec
perl -w -S $0 $argv:q' if 0;
#
use strict;
use diagnostics;
use Parse::RecDescent;

my $grammar = q {

start: identifier(s)

identifier : /\S+/
{ print $item[0]."\n"; }
};
my $parser = Parse::RecDescent->new($grammar);

open(IN,"data.txt") or die "Cannot open data.txt";
# slurp all the lines
my @lines = <IN>;
defined $parser->start(@lines) or die "Didn't match anything";
### end of parser

# data.txt
Head node1
Tail node2
 
P

Peter J. Holzer

I am new to Parse::RecDescent and I came across this problem of the
parser not being able to ignore the newline character. Is there a way
I can ask the parser to ignore all newlines? [...]
open(IN,"data.txt") or die "Cannot open data.txt";
# slurp all the lines
my @lines = <IN>;
defined $parser->start(@lines) or die "Didn't match anything";

You are calling $parser->start with two arguments here: "Head node1\n"
and "Tail node2\n".

AFAICS this isn't allowed. (But the error message is strange - I guess
Parse::RecDescent uses a second parameter for internal and undocumented
purposes.

So I think your question is really: How can I read in an entire file all
at once?

This is a FAQ. read

perldoc -q 'entire file'

hp
 
F

freesoft12

Thanks for the pointer to the perldoc section! I tried this suggestion
in that section and I did not get the newline problem:

$var = do { local $/; <INPUT> };

My updated prog is:
my $grammar = q {

start: identifier(s)

identifier : /\S+/
{ print $item[1]."\n"; }
};
my $parser = Parse::RecDescent->new($grammar);

open(IN,"data.txt") or die "Cannot open data.txt";
# slurp all the lines
my $var = do { local $/; <IN> };
#my @lines = <IN>;
defined $parser->start($var) or die "Didn't match anything";

It now prints:
Head
node1
Tail
node2

Like I wanted it to print.

Regards
John
 
U

Uri Guttman

fc> Thanks for the pointer to the perldoc section! I tried this suggestion
fc> in that section and I did not get the newline problem:

fc> $var = do { local $/; <INPUT> };

use File::Slurp. cleaner and faster. especially since you are using a
slower parser.

uri
 
C

C.DeRykus

Thanks for the pointer to the perldoc section! I tried this suggestion
in that section and I did not get the newline problem:

$var = do { local $/; <INPUT> };

My updated prog is:
my $grammar = q {

start: identifier(s)

identifier : /\S+/
            { print $item[1]."\n"; }};
my $parser = Parse::RecDescent->new($grammar);

open(IN,"data.txt") or die "Cannot open data.txt";
# slurp all the lines
my $var = do { local $/; <IN> };
#my @lines = <IN>;
defined $parser->start($var) or die "Didn't match anything";

It now prints:
Head
node1
Tail
node2

And you don't really need to slurp:

while (<IN>)
{
defined $parser->start($_)
or die "Didn't match anything";
}
 
P

Peter J. Holzer

Thanks for the pointer to the perldoc section! I tried this suggestion
in that section and I did not get the newline problem: [...]
my $parser = Parse::RecDescent->new($grammar);

open(IN,"data.txt") or die "Cannot open data.txt";
my $var = do { local $/; <IN> };
defined $parser->start($var) or die "Didn't match anything";
[...]
And you don't really need to slurp:

while (<IN>)
{
defined $parser->start($_)
or die "Didn't match anything";
}

That parses every line separately which is in general not the same as
parsing a whole file.

hp
 
C

C.DeRykus

[...]
And you don't really need to slurp:
while (<IN>)
{
        defined $parser->start($_)
              or die "Didn't match anything";
}

That parses every line separately which is in general not the same as
parsing a whole file.

Right, a simple example like the OP's, doesn't but even
a slightly more complex grammar could. For instance, if
the grammar required a blank line too:


start: identifier(s) blank

identifier : /\S+/
{ print $item[1],"\n"; }

blank: /^$/
{ print "blank...\n"; }


Then, you'd need to slurp... I think.
 
F

freesoft12

I can't slurp as my orig grammar has a hierarchy to it (meaning that
the identifiers belong to a group and that group belongs to another
etc). I only used a small example to post. I will have to slurp the
whole file rather than passing in every line.

Regards
John
 
U

Uri Guttman

fc> I can't slurp as my orig grammar has a hierarchy to it (meaning that
fc> the identifiers belong to a group and that group belongs to another
fc> etc). I only used a small example to post. I will have to slurp the
fc> whole file rather than passing in every line.

that makes no sense as that is what slurping is - reading in the whole
file at one time into an array or scalar. sometimes parsing is much
easier and faster when the entire file is in a scalar. since P::RD can't
parse incrementally it does better when you slurp. and yes, slurping is
the technical term! check out File::Slurp for more.

uri
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top