我的代码在正则表达式插值上花费了大量时间。由于模式很少改变,我想缓存这些生成的正则表达式应该会加速代码。但是我无法找到缓存和使用缓存的正则表达式的正确方法。
该代码用于解析一些算术表达式。由于允许用户定义新的运算符,解析器必须准备好向语法中添加新的运算符。所以解析器使用一个表来记录这些新的操作符,并动态地从表中生成正则表达式。
#! /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
最佳答案
以下内容不能直接回答您的问题,但可能会引起您的兴趣。
用户定义的运算符
以下代码在 P6 中声明了一个运算符:
sub prefix:<op> ($operand) { " $operand prefixed by op" }
现在可以使用 new 运算符:
say op 42; # 42 prefixed by op
涵盖了广泛的运算符位置和参数,包括结合性和优先级的选择、分组的括号等。所以这也许是实现您正在实现的内容的合适方法。
虽然它很慢,但它可能足够快。此外,作为拉里 said in 2017 ...
we know some some places in the parser that are slower than they should be, for instance ... various lexers relook at various characters in your Perl 6 program, it averages 5 or 6 times on every character, which is obviously deeply sub-optimal, and we know how to fix it
... 幸运的是 Jonathan will work on the P6 grammar parser this year .
DSL 和俚语
即使您对使用主语言声明用户定义的运算符的能力不感兴趣,或者由于某种原因不能,使其工作的底层机制可能会引起兴趣/使用。以下是一些引用:
关于regex - 如何缓存和使用 perl6 语法中缓存的正则表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54266969/