Hanken has asked for the wisdom of the Perl Monks concerning the following question:

Hi, Guys, I am new to PRD. I knew there are many topics on skipping C comments in parser, but I failed to make it work in my perl script. Can anybody show me an example or just fix my script blow.
#! /usr/local/bin/perl -sw BEGIN { close STDERR and open STDERR, '>./STDERR' or die $!; } use Parse::RecDescent; #============================================ # GRAMMAR DEFINITION HERE #============================================ $grammar = q{ Para: List(s) /\Z/ | { use Data::Dumper 'Dumper'; print "$_->[0]\n" for @{$thisparser->{errors}}; exit; } List: #<skip: here???> Order Name Score Prize | <error: error 0!> Order: /\d+/ {print "@item\n";} | <error: error 1!> Name: /\w+/ {print "@item\n";} | <error: Expecting a name!> Score: /\d+/ {print "@item\n";} | <error: error 2!> Prize: <skip: /\/\/.*\n/> /[^\n]+/ {print "@item\n";} }; #============================================ # MAIN PROGRAM STARTS HERE #============================================ $parse = new Parse::RecDescent ($grammar); my $text = do { local $/; <DATA> }; $parse->Para($text); __DATA__ 1 Pig 100 red flower // 1 can this be removed? 2 Han 80 bread /* 2 I want this removed! */ 3 Hen 50 ass kicked /* 3 this comment should be handled too */ 3 Fdi 99 rose /* 4 failed msg if unbalanced comment here

BTW: my script works well if there is no comment in <data>.

Replies are listed 'Best First'.
Re: PRD parser problem: How to skip C comments when parsing
by andreas1234567 (Vicar) on Jun 10, 2008 at 06:49 UTC
Re: PRD parser problem: How to skip C comments when parsing
by ikegami (Patriarch) on Jun 10, 2008 at 07:03 UTC

    Assuming you don't allow comment nesting or /*/, a C comment is

    qr{ /\* .*? \*/ }sx

    You said C, but your example also shows a C++ comment. A C++ comment is

    qr{ // [^\n]* }x

    The default definition of whitespace in PRD is

    qr{ \s* }x

    So if we combine them all, we get

    Para: <skip:qr{ (?> \s | /\* .*? \*/ | // [^\n]* )* }sx> List(s) /\Z/

    <skip> is dynamically scoped, so List and everything called by it will be affected.

      Thanks ikegami! But your change seems not fix my script. I cannot get the right result when I change my script with your kind suggestion.
      the error log: error 1! error 0!

        Did you forget to remove <skip: /\/\/.*\n/> from Prize?

        You'll still get an error, though, because your data is invalid based on your definition of Prize. You've previously indicated or implied that the Prize is the rest of the line. You have changed you definition of Prize without adjusting your grammar to compensate. You probably want something like:

        Prize: /(?:(?!\n|\/\*|\/\/).)*/