Интерполяция переменных в регулярном выражении Parse :: RecDescent - PullRequest
2 голосов
/ 09 июня 2009

Я работаю над грамматикой Parse :: RecDescent, чтобы прочитать заданный человеком понятный набор правил, а затем выплюнуть файл, который намного легче читать компьютеру.

Одним из токенов является список «ключевых слов»; около 26 разных ключевых слов. Они могут изменяться со временем, и на них могут ссылаться несколько фрагментов кода. Следовательно, я хочу сохранить ключевые слова в файле данных и загрузить их.

Особенностью Parse :: RecDescent является возможность интерполировать переменные в регулярных выражениях, и я хотел бы использовать это.

Я написал некоторый код в качестве доказательства концепции:

@arr = ("foo", "bar", "frank", "jim");


$data = <<SOMEDATA;
This is some data with the word foo in it
SOMEDATA

$arrstr = join("|", @arr);

if($data =~ /($arrstr)/)
{
    print "Matched $1\n";
}
else
{
    print "Failed to match\n";
}

Это сработало правильно. Когда я перешел к своей основной программе для ее реализации, я написал:

{
    my $myerror = open(FILE, "data.txt") or die("Failed to open data");
    my @data_arr = <FILE>;
    close FILE;
    my $dataarrstr = join("|", @data_arr);

}
#many rules having nothing to do with the data array are here...

event : /($dataarrstr)/
    { $return = $item[1]; }
    | 

И в этот момент я получил эту ошибку от P :: RD: ERROR (line 18): Invalid event: Was expecting /($dataarrstr)/.

Не знаю почему. У кого-нибудь есть идеи, которые могли бы помочь мне здесь?

редактирование: Это не ограниченная проблема - я пробовал это. Я также попробовал синтаксис m {...}.

1 Ответ

3 голосов
/ 09 июня 2009

После изучения документации и очень похожего вопроса на http://perlmonks.org/?node_id=384098, я разработал это решение.

event :/\w+/
    {
        $return = ::is_valid_event($item[1]);
    }
    | <error>

Вне грамматики -

#This manages the problem of not being able to interpolate the variable 
#in the grammar action
sub is_valid_event {
    my $word = shift @_;
    if($word =~ /$::data_str/)
    {
        return $word;
    }
    else
    {
        return undef;
    }
}
...