基于条件字符替换的字符串替换算法



用例:我正在为一个类似regex但功能更强大的Lispy字符串处理系统编写一个特定于领域的语言(DSL),该系统专注于条件替换(比如为编程人员/语言学家模拟语言进化),而不是像regex那样匹配。像往常一样,我在实际写代码之前先写了规范。

然而,由于一个有点愚蠢但难以修复的错误,我最终得到了一个系统,每次只能处理一个字符。因此,重写规则可能是(在伪代码中)change 'a' to 'e' when last char is 's' and next char is 'd'。也可以删除字符:delete 'a' when ... .

由于DSL的解释器有点像意大利面(不是在非结构化的意义上,而是在1。我还没有为我在Chicken Scheme 2中的实现找到OO。没有IDE,所以必须记住20多个变量名并使用emacs)我不想碰它,而是"非糖"字符串替换为条件字符替换。

举个简单的例子:change "ab" to "cd" unconditionally重写为change 'a' to 'c' when followed by 'b'; change 'b' to 'd' when preceded by a。然而,当有条件时,事情很快就会变得非常糟糕。是否有一些简单的递归方法来重写,或者这在重写阶段几乎是不可能的,我可能应该修复我的DSL解释器?(注意:我的DSL有方法获得当前字符前后的第n个字母)

问题是,由于我们是一次一个字符地遍历数据,当一个条件应用于一个多字符字符串时,该条件必须以不同的方式表示每个位置。例如,"abc" followed by "x"以一种直接的方式组合成abc的条件,但必须改变形状。x实际上离a有三个位置,但离b只有两个位置。这是不好的,因为它会导致条件的激增,这些条件都被浪费地求值。

我将通过在解释器中添加框架的概念来解决这个问题。在当前字符位置建立帧,然后以某种方式保持该位置,允许字符的帧相对寻址。

我可以想到几种方法来介绍这个位置固定。一种是在解释器中引入变量绑定。它可以支持一对指令bind symbolunbind n,其中我们将使用gensym符号。

在生成对字符串(如"abc")进行操作的代码时,我们会生成一条类似bind #:g0025的指令,该指令将固定a的位置,然后编译器将分析应用于字符串的条件,并将其重新描述为相对于#:g0025的条件。在处理完"abc"之后,我们会发出unbind 1来删除最近绑定的变量。

还可以将变量绑定到条件的布尔值。

作为命名框架的一个例子,假设我们有
Replace "abc" with "ijk" when preceded by "x" and followed by "yz".

这样写:

bind #:frame
bind #:cond0 to when #:frame[-1] is "x" and #:frame[3] is "y" and #:frame[4] is "z"
replace "a" with "i" when #:cond0  ; these insns move the char position
replace "b" with "j" when #:cond0 
replace "c" with "k" when #:cond0
unbind 2

因此,难点已经转化为将条件编译成帧相关寻址的难点。#:frame[3]是从"abc"模式的长度派生出来的,它一次对翻译人员可用。这些信息在目标语言中是不可用的,因为目标语言没有一次性的"abc"

系统几乎肯定需要某种方法在同一位置尝试不同的匹配。如果当前位置没有"abc",则必须在同一位置尝试另一个替换"foo"的规则。也许当条件失效时,指令没有推进字符位置。所以在我们上面的例子中,这是可行的:所有指令共享相同的条件,所以在匹配的情况下,位置移动三个位置,否则不移动。然而,尽管如此,可能需要在同一地点进行不同条件的多个编辑。不过,我的回答范围并不是设计整个东西。

最新更新