令$ sigma $为一组终端,$ n $是某些无上下文的语法$ g $的非终端符号。

说我有一个字符串$ a in( sigma cup n)^+$,以便$ xay in mathcal {s}(g)$其中$ x,y in( sigma cup cup n)^** $和$ MATHCAL {S}(G)$是$ G $的句子形式。

给定的$ g $,我想确定一组$ c = {b mid wabz in mathcal {s}(g),b in sigma cup n } $。

为了澄清,在这种情况下,$ W,X,Y,Z,A,B $是终端和非终端的字符串,$ b $是长的。

如果$ a $也有长度,我可以看到如何做到这一点;每个$ b $都是以下$ A $(包括非终端)的成员。

但是,我很好奇是否有一系列字符。对于我的应用程序,字符串$ a $不超过$ g $的作品的右侧。

终端和非末端之间的区别在我的应用中有些静音,因为我使用了生成语法。而且我相信,这不会带来太大的麻烦,因为$ b $是长时间的。

有帮助吗?

解决方案

我将描述一种有效的算法。运行时间还不错。您也可以对此进行大量计算。

我假设$ a $不包含非终端(尽管可能很容易适应该情况),并且您不知道$ x $,$ y $或$ a $的推导。我还假设您的语法不包含任何派生中从未使用过的作品(例如,$ a rightarrow a $)。

主要问题是要解析$ a $,因为您想知道您最终进入的状态,因此您知道可以跟随$ $ $。这并不容易,因为您不知道$ x $。

我们使用适应 Earley的算法. 。您需要先了解该算法。我们的算法几乎以相同的方式工作,除了我们的初始化和完成步骤不同。

对于初始化,我们将在每次出现的$ a_1 $($ a $中的第一个字符)中使用Earley物品播种。我们将此项目的后背指针设置为-1,一个无效的值。这对于我们修改的完成很重要。从本质上讲,-1表示“我不知道该作品的开始何方”。

现在,我们为所有可能的初始Earley项目分别执行Earley算法。我们不能简单地同时完成所有这些工作,因为解析可能会互相干扰。我看不到比在这里回溯更快的方法。

对于完成步骤,我们只需进行修改即可处理-1个背部指针。当我们完成了我们不知道的起源的作品时,我们遇到了麻烦。然而, 用于计算$ lalr(1)$ lookahead sets的方法 经过 Pennello和Deremer 拯救我们:我们在这里需要的恰恰是$ lalr(1)$ lookahead套装。这些LookAhead集合中的每个项目在语法中都有相应的位置,这反过来对应于完成的生产的可能延续。

不幸的是,除了再次回溯之外,我真的没有其他选择。对于LookAhead集合中的每个位置,您都可以使用此位置执行完成步骤,然后从那里继续解析。您可以为每个分析单独执行此操作。请注意,如果您的语法为$ lalr(1)$,则您的LookAhead将唯一确定您必须去哪个位置,因此您不必回溯。

您将继续上述算法超出$ a $的一个字符,您将这个额外的虚拟字符视为“任何字符”,这立即为您提供了您要寻找的“关注”集 - 任何时候扫描仪阶段找到一些东西最终组合,您可以将此字符添加到答案集中。

编辑: 我认为我已经找到了删除回溯介绍的大部分开销的方法。我们将每个earley项目与字符串相关联,因为我们需要使用这些标识符的前缀。初始化时,我们将所有初始项目添加到Earley集合中,并将唯一标识符与每个集合相关联。

在扫描仪和预测器步骤上,标识符被转移到新项目中。 Earley项目中仅将标识符合并在一起的同一EARLEY集合中,其标识符合并在一起。请注意,我们可以使用标识符对这些新项目进行扫描仪和预测步骤,而无需分别为每个标识符执行此步骤。

完成者分别考虑标识符,并且仅在较早的项目集中的相应项目具有标识符的前缀为标识符的前缀时才完成项目。对于每个可能的完成(因此,对于$ lalr(1)$ LookAhead集中的每个项目),我们将一个唯一的字符附加到已完成项目的标识符上。

从本质上讲,我们使用这些标识符进行回溯,以免在扫描仪和预测器步骤中进行双重工作。

许可以下: CC-BY-SA归因
不隶属于 cs.stackexchange
scroll top