繁体   English   中英

如何扩展此语法的项目集?

[英]How do I expand the item set for this grammar?

我有这个语法

E -> E + i
E -> i

增广语法

E' -> E
E -> E + i
E -> i

现在我尝试扩展项目集 0

I0)
 E' -> .E
+E  -> .E + i
+E  -> .i

然后,由于我在I0.E我会扩展它,但随后我会得到另一个E规则,依此类推,这是我的第一个疑问。

假设这没问题,接下来的项目集是

I0)
 E' -> .E
+E  -> .E + i
+E  -> .i

I1) (I moved the dot from I0, no variables at rhs of dot)
E' -> E.
E -> E. + i
E -> i.

I2) (I moved the dot from I1, no vars at rhs of dot)
E -> E +. i

I3) (I moved the dot from I2, also no vars)
E -> E + i.

然后我会有这个 DFA

I0 -(E, i)-> I1 -(+)-> I2 -(i)-> I3
              |                   |
              +-(∅)-> acpt <-(∅)--+

我错过了一些东西,因为E -> E + i必须接受i + i + ..但 DFA 不会回到 I0,所以对我来说似乎是错误的。 我的猜测是它应该有一个 I0 到 I0 的转换,但是我不知道这与点有关。

你所说的项目集的“扩展”实际上是一个闭包; 这就是我见过的所有算法描述中的描述方式(至少在教科书中)。 像任何闭包操作一样,您只需继续进行转换,直到达到一个不动点; 一旦你包含了E ,它们就会被包含在内。

但关键是您不是在构建 DFA。 您正在构建一个下推自动机,而 DFA 只是其中的一部分。 DFA 用于移位操作; 当你移动一个新的终端时(因为当前的解析堆栈不是一个句柄),你会根据 DFA 进行状态转换。 但是您也将当前状态推送到 PDA 的堆栈中。

有趣的部分是当自动机决定执行归约时会发生什么,它将产生式的右侧替换为其左侧的非终结符。 (堆栈顶部的右侧称为“句柄”。)要进行归约,您需要展开堆栈,弹出每个右侧符号(以及相应的 DFA 状态),直到到达生产。 这样做是将 DFA 倒回到它从右侧移动第一个符号之前的状态。 (请注意,只有在这一点上您才能确定使用了哪个产生式。)因此重置 DFA 后,您现在可以移动遇到的非终结符,执行相应的 DFA 转换,并继续解析。

这个过程的基础是解析器堆栈始终是一个“可行的前缀”; 也就是说,一系列符号是可以从起始符号导出的某些正确句子形式的前缀。 上下文无关文法的一组可行前缀的有趣之处在于,它是一种常规语言,因此可以被 DFA 识别。 当句柄被“修剪”(使用 Knuth 的原始词汇)时,上面给出的减少过程精确地表示了这个识别过程。

从这个意义上说,使用什么过程来确定要修剪哪个句柄并不重要,只要它提供了有效的答案。 例如,您可以在每次在堆栈顶部注意到潜在句柄时分叉解析,并与两个分叉并行继续。 通过巧妙的堆栈管理,可以在任何上下文无关文法的最坏情况 O(n 3 ) 时间内完成这种并行搜索(如果文法没有歧义,则可以减少这种情况)。 这是对 Earley 解析器的一个非常粗略的描述。

但是在 LR(k) 解析器的情况下,我们要求语法是明确的,并且我们还要求我们可以通过从输入流中查看不超过k个符号来识别减少,这是一个 O(1 ) 操作,因为k是固定的。 如果在解析中的每个点我们都知道是否要减少,如果知道选择哪种减少,那么可以按照我上面概述的方式实施减少。 对于固定语法,每次缩减都可以在 O(1) 时间内执行(因为特定语法中右侧的最大大小是固定的),并且由于解析中的缩减次数与语法的大小呈线性关系输入,整个解析可以在线性时间内完成。

这有点不正式,但我希望它可以作为一种直观的解释。 如果您对正式证明感兴趣,Donald Knuth 1965 年的原始论文(关于从左到右的语言翻译)很容易找到,并且随着这些内容的发展具有很高的可读性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM