如何在perl6语法中缓存和使用缓存的正则表达式?

时间:2019-01-19 12:12:46

标签: regex perl6

我的代码在正则表达式插值上花费了大量时间。由于模式很少更改,我想将这些生成的正则表达式缓存起来可以加快代码的速度。但是我无法找出正确的方法来缓存和使用缓存的正则表达式。

该代码用于解析某些算术表达式。由于允许用户定义新的运算符,因此解析器必须准备好将新的运算符添加到语法中。因此,解析器使用表格记录这些新的运算符,并动态地从表格中生成正则表达式。

#! /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 :(得分:4)

以下内容不能直接回答您的问题,但可能会引起您的兴趣。

用户定义的运算符

以下代码在P6中声明一个运算符:

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

现在可以使用新的运算符了:

say op 42; # 42 prefixed by op

涵盖了范围广泛的操作员职位和联系方式,包括对关联性和优先级的选择,用于分组的括号等。因此,这也许是实现您要实现的目标的一种合适方法。

尽管速度很慢,但可能足够快。此外,作为拉里said in 2017 ...

  

我们知道解析器中某些地方的速度慢于应有的速度,例如...各种词法分析器会重新查看Perl 6程序中的各种字符,每个字符平均5到6次,这显然很深次优,我们知道如何解决

...并且很幸运,Jonathan will work on the P6 grammar parser this year

DSL和S语

即使您对使用主语言声明用户定义的运算符的能力不感兴趣,或者由于某种原因而不能使用,使它起作用的基本机制也可能会受到关注/使用。这里是一些参考: