Compiler construction 将CFG展平为结构化代码

Compiler construction 将CFG展平为结构化代码,compiler-construction,compilation,theory,control-flow,control-flow-graph,Compiler Construction,Compilation,Theory,Control Flow,Control Flow Graph,我想将CFG输出到高级代码。通常这很容易;在树上行走,依次渲染每个基本块,用gotos将它们粘在一起 不幸的是,gotos现在已经过时了,大多数现代语言都不支持它们。因此,我需要一些方法,仅使用语言中存在的那些控制流语句将基本块粘合在一起:for,while,do,while,if,break和continue。(我不愿意考虑使用变量构建状态机) 看起来,虽然有算法可以做到这一点,但它们不会在所有情况下都起作用。也就是说,可以仅使用上述有限的控制流结构集来构造无法展平为结构化代码的CFG 这对我

我想将CFG输出到高级代码。通常这很容易;在树上行走,依次渲染每个基本块,用gotos将它们粘在一起

不幸的是,gotos现在已经过时了,大多数现代语言都不支持它们。因此,我需要一些方法,仅使用语言中存在的那些控制流语句将基本块粘合在一起:
for
while
do
while
if
break
continue
。(我不愿意考虑使用变量构建状态机)

看起来,虽然有算法可以做到这一点,但它们不会在所有情况下都起作用。也就是说,可以仅使用上述有限的控制流结构集来构造无法展平为结构化代码的CFG

这对我来说似乎是显而易见的,但我无法证明这一点(我发现的算法文档也没有详细介绍)。我还没有找到一个CFG的例子,它不能像这样展平

我想确切地知道,这是否可能

选项(a):是否有人有如上所述无法展平的CFG示例?(这将告诉我这是不可能的。)


选项(b):是否有人能证明CFG可以如上所述展平?(这将告诉我这是可能的。)一个算法来做这件事也是非常可取的,因为我必须让它工作…

一般来说,你不能仅仅通过在树上行走来展平CFG。这将适用于LL(k)语法,如果您有k个前瞻标记。然而,对于更复杂的语法,如LR(k)语法,需要更复杂的技术。例如,请参见

一般来说,没有解析任何CFG的已知算法,尽管大多数有用的CFG都可以写成LR(k)语法。更多的研究改进了这一点,并且可以解析大类的CFG。我不认为这个问题是无法确定的(尽管我不确定),所以这肯定是有可能的——但我认为这是一个研究问题,不会在这里回答是/否

我还要补充一点,今天所有有价值的语言都是图灵完备的,这意味着你可以用GOTOs做的任何事情都可以用if/while/for/…来完成。。。类型结构。新语言不是限制,而是需要帮助的理论基础


但实际上,您将无法解析所需的任何CFG。但这并不意味着我们不知道将来如何…

一般来说,你不能只是走在树上把CFG压扁。这将适用于LL(k)语法,如果您有k个前瞻标记。然而,对于更复杂的语法,如LR(k)语法,需要更复杂的技术。例如,请参见

一般来说,没有解析任何CFG的已知算法,尽管大多数有用的CFG都可以写成LR(k)语法。更多的研究改进了这一点,并且可以解析大类的CFG。我不认为这个问题是无法确定的(尽管我不确定),所以这肯定是有可能的——但我认为这是一个研究问题,不会在这里回答是/否

我还要补充一点,今天所有有价值的语言都是图灵完备的,这意味着你可以用GOTOs做的任何事情都可以用if/while/for/…来完成。。。类型结构。新语言不是限制,而是需要帮助的理论基础


但实际上,您将无法解析所需的任何CFG。但这并不意味着我们不知道将来如何…

我想我有一个结果

答案似乎是:这是不可能的。这是来自1966年朱塞佩·雅科皮尼(Giuseppe Jacopini)在《ACM通讯》第9卷第366至371页的一篇论文《流程图、图灵机和只有两种形成规则的语言》。(有趣的是,我发现引用Knuth的开创性的(而且,在我看来,令人难以置信地恼火)Go-To声明被认为是有害的。)

令人失望的是,他们没有证据,说他们找不到证据


好消息是,这篇论文确实描述了一种策略,即使用尽可能少的状态,仅使用有限的控制流机制,将任意CFG转换为CFG。这篇论文很难,但看起来很有希望。

我想我有一个结果

答案似乎是:这是不可能的。这是来自1966年朱塞佩·雅科皮尼(Giuseppe Jacopini)在《ACM通讯》第9卷第366至371页的一篇论文《流程图、图灵机和只有两种形成规则的语言》。(有趣的是,我发现引用Knuth的开创性的(而且,在我看来,令人难以置信地恼火)Go-To声明被认为是有害的。)

令人失望的是,他们没有证据,说他们找不到证据


好消息是,这篇论文确实描述了一种策略,即使用尽可能少的状态,仅使用有限的控制流机制,将任意CFG转换为CFG。这篇论文很难,但看起来很有希望。

虽然这个问题很久以前就被问到了,但实际上这似乎是可能的。Mozilla在将LLVM编译为JS(或现在的WebAssembly)时也遇到了类似的问题。JS和WebAssembly只允许结构化控制流,而LLVM允许任意控制流

他们写了一篇关于这一点的论文,也用于:

这一思想是以美国的算法为模型的。有证据表明,任何控制流都可以以结构化的方式表示,只需使用JavaScript中可用的控制流结构,并使用Tilt语义中提到的类似于标签的辅助变量,而不需要任何代码复制(其他方法会分割节点,并具有坏的性能)