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

发布于 2024-11-17 18:09:04 字数 813 浏览 4 评论 0原文

我有一个词法分析器/解析器对(几年前我抄袭了别人)。我将添加几个功能,并认为我将首先标准化包含多个 if/else if/else 的 while(true) 的使用,而不是使用 goto 跳回到开关之前的开关。

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

while(true) 和嵌套开关的问题是,break 只能从开关中突破出来,而不能超出 while 之外。

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

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

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

一般来说,词法分析器代码似乎通过删除 while(true) 并在开关开始之前放置一个标签并使用 goto 继续循环来解决这个问题。这使得break意味着停止循环,说实话,这似乎是最干净的方法,但确实涉及到可怕的goto。

回到 while(true) ,我还可以看到第三种方式。在 while(true) 之后使用标签,并让 switch 代码使用 goto 在循环应该结束时到达它。 Break 则意味着退出开关但继续循环。

那么专家组对此有何看法呢? goto 是不是太难用了?或者,当只有一个标签可以跳转并减少缩进并生成清晰的代码时,是否可以?解析器/词法分析器是否应该获得使用 goto 的特殊许可?

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

I have a lexer/parser pair (which I cribbed off someone else years ago). I am going to be adding a couple of features and thought I would first standardise the use of while(true) containing multiple if/else if/else vs a switch which uses a goto to jump back to before the switch.

(Before the flames start, I don't normally use goto as its evil etc. etc.)

The problem with a while(true) and a nested switch is that the break only breaks out of the switch and cannot get outside the while.

I have done some searching here and seen suggestions to use a return from inside the switch. Whilst this would work in some cases, in others, there is some processing after the while but before returning. Duplicating this code in multiple places doesn't really appeal.

I could also introduce a boolean flag and use that in the while statement to decide whether to break out of the while but that also doesn't appeal as it adds noise to the code.

The current way in the parser of using if/else if/else instead of an inner switch works but I do have a preference for a switch if possible.

The lexer code in general seems to get around this by removing the while(true) and putting a label just before the switch start and using goto to continue the loop. This leaves break meaning stop the loop and, to be honest, seems the cleanest way but does involve the dreadead goto.

Going back to the while(true), I can also see a third way. Use a label after the while(true) and let the switch code use goto to get to it when the loop should end. Break would then mean exit the switch but continue the loop.

So what are the panels views on this? Is goto too abhorrent to use? Or is it OK when there is just a single label to jump to and reduces indenting and produces otherwise clear code? Should parsers/lexers get special license to use gotos?

I can provide some sample code if it would help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若沐 2024-11-24 18:09:04

以严格的方式使用 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;
             ...
                            }
                       }

如果你的语言中存在 exit 结构,那么它就会退出
由指定标签标记的块。 (没有任何借口
对于现代语言来说没有这个,但是,我没有
设计它们)。

作为穷人的替代品,这样写是完全令人满意的:

   <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< /em> 嵌套块”。这是一个极其愚蠢的想法,因为一些糟糕的维护者可能随后会在堆栈中的某个位置插入另一个块,而现在代码会做出疯狂的事情。 (事实上​​,大约 20 年前,电信交换机中的这个错误就导致了整个东海岸的电话系统瘫痪)。如果您在您的语言中看到这种结构,请使用穷人的替代品。

Use of GOTO in disciplined ways is fine. Languages which don't allow breaks out of arbitrarily nested block structures cause this question to be raised repeatedly, since the 1970s when people beat the question of "what control flow structures should a langauge have" to death. (Note: this complaint isn't special to lexers/parsers).

You don't want the scheme with boolean; it just adds extra overhead to the loop checks and clutters the code.

I think you have this problem:

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

The proper cure with a good language is:

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

if the exit construct exists in your language, that exits
the blocks labelled by the named label. (There's no excuse
for a modern langauge to not have this, but then, I don't
design them).

It is perfectly satisfactory to write, as a poor man's substitute:

   <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

On occasion you'll find a language that offers

break <exp>

where exp is usually a constant whole number, meaning, "break out of exp nested blocks". This is an astoundingly stupid idea, as some poor maintainer may later come along an insert another block somewhere in the stack, and now the code does crazy things. (In fact, this exact mistake in a telco switch took out the entire East Coast phone system about 20 years ago). If you see this construct in your langauge, use the poor man's substitute instead.

浪菊怪哟 2024-11-24 18:09:04

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

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

因此,如果需要的话请使用 goto。不要仅仅因为你懒得正确思考事情而使用它们。

Within parsers the use of GOTO is perfectly reasonable. When you get down to a base level, the loops and conditions etc are all implemented as gotos, because that is what processors can do - "take the next instruction to be executed from here".

The only problems with gotos, and the reason they are so often demonised, is that they can be an indication of unstructured code, coming form unstructured thinking. Within modern high level languages, there is no need for gotos, because all of the facilities are available to structure code well, and well structured code implies at least some structured thinking.

So use gotos if they are needed. Don't use them just because you can't be bothered to think things through properly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文