psgels psgels - 6 months ago 18
Perl Question

Case-insensitive hash-keys in Regexp::Grammars

In the perl module Regexp::Grammars, consider the following token:

<token: command> <%commands>


This token is part of a complex grammar, parsing a wide variety of different sentences.

This token matches any word in the hash %commands, which I have defined as follows (of course, outside any function):

our %commands = (
'Basic_import' => 1,
'Wait' => 1,
'Reload' => 1,
'Log' => 1,
);


This works, for matching keywords like "Basic_import", "Wait", etc. However, I also want it to match on words like "basic_import", "wait", etc.

How do I make this hash case insensitive without having to copy and paste every keyword multiple times? Because this is part of a complex grammar, I want to use Regexp::Grammars, and I'd prefer not to have to revert to a grep for this particular exception.

Answer

You can use Tie::Hash::Preserve to make hash lookups case insensitive:

use strict;
use warnings 'all';

use Data::Dump;
use Hash::Case::Preserve;
use Regexp::Grammars;

tie my %commands, 'Hash::Case::Preserve';

%commands = (
    'Basic_import'  => 1,
    'Wait'          => 1,
    'Reload'        => 1,
    'Log'           => 1,
);

my $grammar = qr{

    <command>

    <token: command>    <%commands>

};  

dd \%/ if 'basic_import' =~ $grammar;

Output:

{ "" => "basic_import", "command" => "basic_import" }

Note that you have to tie the hash before inserting any values into it.

Comments