Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Matching terminals with Parse::RecDescent

by fce2 (Sexton)
on Dec 11, 2006 at 21:17 UTC ( #589153=perlquestion: print w/replies, xml ) Need Help??

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

When matching terminals, Parse::RecDescent seems to produce a match if a token begins with the terminal, rather than trying for an exact match. This code demonstrates this:

#!/usr/bin/perl use warnings; use strict; use Parse::RecDescent; my $grammar = q{ FOO: "foo" }; my $p = Parse::RecDescent->new($grammar); my @tests = ("foo", "foo ", "foo bar", "football", "fog", "barfoo", "b +ar foo"); for my $test (@tests) { if (my $ret = $p->FOO($test)) { print "match: '$test' -> '$ret'\n"; } else { print "no match: '$test'\n"; } }

This isn't what I want. I want it to produce an error/return undef when what was entered doesn't match in full, rather than simply eating the remainder.

I doubt this is a bug, because it seems too trivial, so I suspect that this is actually a lack of understanding of parsing in general on my part. Could someone please set me straight here? Thanks!

Replies are listed 'Best First'.
Re: Matching terminals with Parse::RecDescent
by GrandFather (Saint) on Dec 11, 2006 at 21:30 UTC

    You need to force a end of line (or end of file) match. For the sample given, changing your grammar to:

    FOO: /foo$/

    does the trick. In the context of a file being parsed you are more likely to want

    FOO: "foo" /\Z/

    DWIM is Perl's answer to Gödel
      /foo$/ works for the example script. "foo" /\Z/ didn't match anything (though /foo\Z/ did). All fall down if I test with this grammar:
      line: FOO BAR FOO: /foo\Z/ BAR: /bar\Z/
      (and use $p->line instead of $p->foo). I probably should have been more specific, but I'm looking for a more generalised solution to this, or at least some understanding of where my expectations are wrong.

        or at least some understanding of where my expectations are wrong.

        Your grammar expects to match

        1. 0 or more whitespace characters (see <skip>),
        2. followed by "foo",
        3. followed by the end of the string to parse,
        4. 0 or more whitespace characters,
        5. followed by "bar",
        6. followed by the end of the string to parse.

        With the grammar:

        line: FOO BAR /$/ FOO: "foo" BAR: "bar"

        and the invocation changed line to:

        if (defined (my $ret = $p->line($test))) {

        I get:

        no match: 'foo' no match: 'foo ' match: 'foo bar' -> '' no match: 'football' no match: 'fog' no match: 'barfoo' no match: 'bar foo'

        Is that not what you expect?


        DWIM is Perl's answer to Gödel

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://589153]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2022-07-03 08:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?