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

标签 regex raku

我的代码在正则表达式插值上花费了大量时间。由于模式很少改变,我想缓存这些生成的正则表达式应该会加速代码。但是我无法找到缓存和使用缓存的正则表达式的正确方法。

该代码用于解析一些算术表达式。由于允许用户定义新的运算符,解析器必须准备好向语法中添加新的运算符。所以解析器使用一个表来记录这些新的操作符,并动态地从表中生成正则表达式。

#! /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 和俚语

即使您对使用主语言声明用户定义的运算符的能力不感兴趣,或者由于某种原因不能,使其工作的底层机制可能会引起兴趣/使用。以下是一些引用:
  • Brian Duggan 的非正式 DSL 演示文稿 ( video , slides )。
  • Mouq 2014 年要点 Slangs .
  • 拉里·沃尔早在 Switching parsers and Slangs 时的猜测.
  • 关于regex - 如何缓存和使用 perl6 语法中缓存的正则表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54266969/

    相关文章:

    string - 为什么用:w and :append still overwrite the file?打开

    java - 在 Android 中使用正则表达式将 "- "替换为空格

    python - 使用通配符搜索和替换文本文件中的字符串

    javascript - inherit.js 中的奇怪正则表达式(John Resig 着)——为什么、什么以及如何?

    mysql - 在 rakudo-star docker 镜像上安装带有 DBIish 的 mysql 的安装要求

    raku - 如何防止perl编译器更改动态链接库的名称

    raku - 在 raku 中取消绑定(bind)或取消定义变量

    c# - ASP.NET 正则表达式 -validationExpression

    javascript - 奇怪的javascript导致错误

    raku - 如何将2元素列表做成哈希表?