我的代码花了很多时间在正则表达式插值上.由于模式很少改变,我想缓存这些生成的正则表达式应该加快代码.但我无法找到一种正确的方法来缓存和使用缓存的正则表达式.
该代码用于解析一些算术表达式.由于允许用户定义新运算符,因此解析器必须准备好将新运算符添加到语法中.因此,解析器使用表来记录这些新运算符,并在运行时从表中生成正则表达式.
#! /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:
# ?+?
Run Code Online (Sandbox Code Playgroud)
以下是一些实验:
# 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
Run Code Online (Sandbox Code Playgroud)
# 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
Run Code Online (Sandbox Code Playgroud)
以下内容不会直接回答您的问题,但可能会引起您的兴趣。
以下代码在 P6 中声明一个运算符:
sub prefix:<op> ($operand) { " $operand prefixed by op" }
Run Code Online (Sandbox Code Playgroud)
现在可以使用 new 运算符:
say op 42; # 42 prefixed by op
Run Code Online (Sandbox Code Playgroud)
涵盖了广泛的运算符位置和参数,包括关联性和优先级的选择、分组的括号等。因此,也许这是实现您正在实现的内容的合适方法。
虽然很慢,但也可能足够快了。此外,正如 Larry在 2017 年所说……
我们知道解析器中的某些地方比应有的速度慢,例如...各种词法分析器重新查看 Perl 6 程序中的各种字符,每个字符平均执行 5 或 6 次,这显然不是最理想的,我们知道如何解决它
...幸运的是,Jonathan 今年将致力于 P6 语法解析器。
即使您对使用主语言声明用户定义运算符的能力不感兴趣,或者由于某种原因不能,也可能会感兴趣/使用使其工作的底层机制。以下是一些参考:
Mouq 的 2014 年要点俚语。
拉里·沃尔(Larry Wall)很久以前在《切换解析器和俚语》中的猜测。