regexperlregexp-grammars

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.


Solution

  • You can use Hash::Case::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.