在词法分析器/解析器中使用Goto

时间:2011-06-30 08:57:53

标签: c# parsing goto lexer

我有一个词法分析器/解析器对(几年前我把其他人扯掉了)。我将添加一些功能,并认为我首先将使用while(true)包含多个if / else if / else vs一个使用goto跳转回切换的开关标准化。

(在火焰开始之前,我通常不会使用goto作为它的邪恶等等。)

一段时间(真实)和嵌套开关的问题在于,断点只会从交换机中断开,并且无法在此时间之外。

我在这里做了一些搜索,并看到了从交换机内部使用返回的建议。虽然这在某些情况下会起作用,但在其他情况下,会在一段时间之后但在返回之前进行一些处理。在多个地方复制此代码并不具有吸引力。

我还可以引入一个布尔标志,并在while语句中使用它来决定是否突破,但这也没有吸引力,因为它会给代码增加噪音。

解析器中当前使用if / else if / else而不是内部开关的方式有效,但如果可能,我确实喜欢切换。

lexer代码似乎通过删除while(true)并在切换开始之前放置标签并使用goto继续循环来解决这个问题。这留下了休息意味着停止循环,说实话,这似乎是最干净的方式,但确实涉及dreadead goto。

回到原点(真实),我还可以看到第三种方式。在while(true)之后使用标签,并在循环结束时让开关代码使用goto到达它。然后,中断意味着退出交换机,但继续循环。

那么小组对此有何看法?是不是太可恶了?或者只有一个标签可以跳转并减少缩进并生成其他清晰的代码?解析器/词法分析者是否应获得使用gotos的特殊许可?

如果有帮助,我可以提供一些示例代码。

2 个答案:

答案 0 :(得分:3)

以纪律严明的方式使用GOTO很好。不允许突破任意嵌套的块结构的语言导致这个问题反复提出,因为20世纪70年代人们打破了“语言控制流程应该具有什么样的控制流”的问题。 (注意:此投诉对词法分析器/解析器并不特殊)。

你不希望这个方案有布尔值;它只会给循环检查增加额外的开销并使代码混乱。

我认为你有这个问题:

   <if/while/loop head> {
       <if/while/loop head> {
             ...
                 if <cond>  <want to break out all blocks>
             ...
                            }
                       }

用良好的语言进行适当的治疗是:

  blocks_label:
  <if/while/loop head> {
       <if/while/loop head> {
             ...
                 if <cond>  exit blocks_label;
             ...
                            }
                       }

如果您的语言中存在退出构造,则退出 由指定标签标记的块。 (没有任何借口 对于现代语言来说,没有这个,但是,我没有 设计他们)。

作为一个穷人的替补写作是完全令人满意的:

   <if/while/loop head> {
       <if/while/loop head> {
             ...
                 if <cond>  goto exit_these_blocks;
             ...
                            }
                       }
   exit_these_blocks:  // my language doesn't have decent block exits

有时你会找到一种提供

的语言
break <exp>

其中 exp 通常是一个常数整数,意思是“突破 exp 嵌套块”。这是一个令人惊讶的愚蠢想法,因为一些不好的维护者可能会在堆栈中的某个位置插入另一个块,现在代码会做疯狂的事情。 (实际上,电信交换机中的这个错误的错误在大约20年前取消了整个东海岸电话系统)。如果你在语言中看到这个结构,请改用穷人的替代品。

答案 1 :(得分:2)

在解析器中,使用GOTO是完全合理的。当你到达基级时,循环和条件等都被实现为gotos,因为这就是处理器可以做的事情 - “从下面执行下一条指令”。

gotos的唯一问题,以及它们经常被妖魔化的原因在于它们可以表示非结构化代码,来自非结构化思维。在现代高级语言中,不需要getos,因为所有的工具都可以很好地构建代码,而结构良好的代码至少意味着一些结构化思维。

如果需要,请使用gotos。不要仅仅因为你不能为正确思考而烦恼。