Как кэшировать и использовать кэшированные регулярные выражения в грамматике perl6? - PullRequest
0 голосов
/ 19 января 2019

Мой код тратит много времени на интерполяцию регулярных выражений.Поскольку шаблоны редко меняются, я думаю, кэширование этих сгенерированных регулярных выражений должно ускорить код.Но я не могу найти правильный способ кэширования и использования кэшированных регулярных выражений.

Код используется для анализа некоторых арифметических выражений.Поскольку пользователям разрешено определять новые операторы, анализатор должен быть готов добавлять новые операторы в грамматику.Поэтому анализатор использует таблицу для записи этих новых операторов и генерирует регулярные выражения из таблицы на лету.

#! /usr/bin/env perl6

use v6.c;

# the parser may add new operators to this table on the fly.
my %operator-table = %(
    1 => $['"+"', '"-"'],
    2 => $['"*"', '"/"'],
    # ...
);

# original code, runnable but slow.
grammar Operator {
    token operator(Int $level) {
        <{%operator-table{$level}.join('|')}>
    }

    # ...
}

# usage:
say Operator.parse(
    '+',
    rule => 'operator',
    args => \(1)
);
# output:
# 「+」

Вот несколько экспериментов:

# try to cache the generated regexes but not work.
grammar CachedOperator {
    my %cache-table = %();

    method operator(Int $level) {
        if (! %cache-table{$level}) {
            %cache-table.append(
                $level => rx { <{%operator-table{$level}.join('|')}> }
            )
        }

        %cache-table{$level}
    }
}

# test:
say CachedOperator.parse(
    '+',
    rule => 'operator',
    args => \(1)
);
# output:
# Nil
# one more try
grammar CachedOperator_ {
    my %cache-table = %();

    token operator(Int $level) {
        <create-operator($level)>
    }

    method create-operator(Int $level) {
        if (! %cache-table{$level}) {
            %cache-table.append(
                $level => rx { <{%operator-table{$level}.join('|')}> }
            )
        }

        %cache-table{$level}    
    }
}

# test:
say CachedOperator_.parse(
    '+',
    rule => 'operator',
    args => \(1)
);
# compile error:
# P6opaque: no such attribute '$!pos' on type Match in a Regex when trying to get a value

1 Ответ

0 голосов
/ 19 января 2019

Следующее не дает прямого ответа на ваш вопрос, но может представлять интерес.

Пользовательские операторы

Следующий код объявляет оператор в P6:

sub prefix:<op> ($operand) { " $operand prefixed by op" }

Теперь можно использовать новый оператор:

say op 42; # 42 prefixed by op

Охватывается широкий диапазон позиций и арных операторов, включая выбор ассоциативности и приоритета, скобки для группировки и т. Д. Так что, возможно, это подходящий способреализовать то, что вы реализуете.

Хотя это медленно, это может быть достаточно быстро.Кроме того, как сказал Ларри в 2017 году ...

, мы знаем, что некоторые места в парсере медленнее, чем должны быть, например ... различные лексеры смотрят наразличных персонажей в вашей программе на Perl 6, в среднем 5 или 6 раз на каждого персонажа, что, очевидно, является глубоко неоптимальным, и мы знаем, как это исправить

... и с удачей Джонатан будет работать над синтаксическим анализатором P6 в этом году .

DSL и сленги

Даже если вы не заинтересованы в использовании основного языка для объявления пользовательских операторов, илине может по какой-то причине, лежащие в основе механизмы, которые заставляют его работать, могут представлять интерес / использование.Вот некоторые ссылки:

...