On Thursday, Nov 20, 2003 Terrence Brannon said: > Tom Kenter wrote: > > >Hello Terrence Brannon, > > > > > > > Hi Tom, > > >This is an email with a question about Parse::RecDescent. I send to you > >because your name was mentioned on the faq page as being the author of > >it. I hope I am right in doing so. If not, please accept my apologies. > > > > > > > I just maintain the FAQ. I don't answer all questions about P::RD. Here > are two resources: > > The Parse::RecDescent Mailing List > http://lists.perl.org/showlist.cgi?name=recdescent > > Perlmonks.org: > www.perlmonks.org > > I have forwarded your email to the former so you might want to join > quickly in case someone answers > soon. > > I am completely out of touch with practical use of P::RD these days. > > >Now, the question is: > >How can I match a single newline in the middle of a rule? > > > >(By the way, I have read these items in the faq list, "NEWLINE > >PROCESSING", "Parsing Windows Init", (.ini) Files", "As end of line", > >but I feel my questions does not get answered there). > > > >This example (form "the man(1) of descent page") works: > >Command: > > LineRange 'c' LineRange > > LeftLine(s) "---\n" RightLine(s) > > { print "$item[3]c$item[1]\n"; > > print map {s/>/</; $_} @{$item[6]}; > > print $item[5]; > > print map {s/</>/; $_} @{$item[4]};} > > > >But this doesn't: > >Command: > > LineRange 'c' LineRange > > LeftLine(s) "\n" RightLine(s) # <-- single newline, without dashes > > { print "$item[3]c$item[1]\n"; > > print map {s/>/</; $_} @{$item[6]}; > > print $item[5]; > > print map {s/</>/; $_} @{$item[4]};} > > > >Why not?
Well, first you are taking this out of context. Second, if you look at the example, the "---" characters ARE ACTUALLY THERE. Remember that the input is a diff output stream and looks like: < left output --- > right output where the "---" characters are a separator. The reason "---\n" works is that P::RD throws away all white space between LeftLine (which !remember! is defined to *include* the \n) and the "---\n", which in this case is null (i.e. there is no white space). In other words it works BECAUSE there is something not white space before the \n. Your example fails because it gets LeftLine (and its associated newline), and then throws away the white space, (which is the "\n" that you wanted!). The example in man(1) of descent works because, as an accident of the input, there is never extra white space to throw away, so Damian didn't bother using <skip>. To make your example work you need the <skip> directive. > >I tried changing it to '\n' and /\n/, and making a new rule > >newline: > > "\n" > > | > > '\n' > > \ > > /\n/ > >all of which to no avail... > > > >Also, I tried this: > > > >### begin listing ### > > > >use strict; > >use Parse::RecDescent; > > > >my $grammar = > > q { > > AdressenGramm: ValidLine(s) > > > >ValidLine: <skip: qr/[ \t]*/> word newline word > > { print "Found $item[1], $item[3]\n"; } > >word: /\w+/ > >newline: /\n/ > >}; > > > >my $parser1 = new Parse::RecDescent($grammar); > > > >my $text = "word1\nword2"; > > > >my $result1 = $parser1->AdressenGramm($text) or warn "Bad input1\n"; > > > >### end listing ### > > > >which has this as output: > >Found \s*, > > > >which was somehow not quite what I expected... Only because you lost count. It found what you wanted, it just did not print it out. If you said print "Found @item\n"; it would have been instantly clear. Remember the <skip> directive (as are *all* items) is entered into the @items array. ValidLine: <skip: qr/[ \t]*/> word newline word 0 1 2 3 4 So print "Found $item[2], $item[4]\n"; would have worked just fine. > > > >What I really want to have is a rule like this: > > > >SeveralLines: > > Word "\n" Word "\n" Word { > > print "found: $item[1], $item[2], $item[3]"; > > } > > > >Word: > > /[A-Za-z]+/ > > > >which would print > >found: abc, def, ghi > >for the input "abc\ndef\nghi"; > > > >I hope to have been both elaborate and brief enough... > > > >Thanks! > > > >Kind regards, > > > >Tom > > > > > > > -- Intel, Corp. 5000 W. Chandler Blvd. Chandler, AZ 85226 -- Intel, Corp. 5000 W. Chandler Blvd. Chandler, AZ 85226