标签和 'goto' 的可接受使用?
Acceptable use of a label and 'goto'?
我正在为编译器编写分词器。我有一个循环遍历字符的 while 循环,然后是一个检查特定条件的开关。然后我需要退出两个块来写入令牌:
Token token;
while (peekChar() != '[=11=]')
{
switch (c = nextChar())
{
case '(':
token = Token(TOKEN_LEFT_PAREN, currentLine);
goto MakeToken;
// ... every other character, some with lots of logic
}
}
MakeToken:
// write the token
这是可以接受的标签使用方式吗?还是有更好的方法?我已经学会将标签视为一种糟糕的做法,但它们肯定有用途(否则它们不会在标准中实现?)。谢谢
您可以在此处使用 break
实现相同的功能,而无需使用 goto
。
我唯一一次在 C++ 中发现一个稍微令人反感的 goto
案例是在一个复杂的状态机中,开发人员非常小心不要弄乱本地状态。
通常,解析器(或更具体地说,分词器)是我进行意大利面式编码的最后一个地方——如果有的话,这需要以更实用的方式使用 C++。
我相信这是接受 goto 的极少数示例之一,但是您可以使用标志:
Token token;
bool flag = true;
while ((peekChar() != '[=10=]') && flag)
{
switch (c = nextChar())
{
case '(':
token = Token(TOKEN_LEFT_PAREN, currentLine);
flag = false;
// ... every other character, some with lots of logic
}
}
一般情况下,当我们想一次break几个作用域的时候,就意味着我们可以做子函数;类似于:
bool HandleChar(char c)
{
switch (c)
{
case '(': {
Token token = Token(TOKEN_LEFT_PAREN, currentLine);
return true;
}
// ... every other character, some with lots of logic
}
}
然后:
while (peekChar() != '[=11=]')
{
if (HandleChar(nextChar())) {
break;
}
}
// ...
我正在为编译器编写分词器。我有一个循环遍历字符的 while 循环,然后是一个检查特定条件的开关。然后我需要退出两个块来写入令牌:
Token token;
while (peekChar() != '[=11=]')
{
switch (c = nextChar())
{
case '(':
token = Token(TOKEN_LEFT_PAREN, currentLine);
goto MakeToken;
// ... every other character, some with lots of logic
}
}
MakeToken:
// write the token
这是可以接受的标签使用方式吗?还是有更好的方法?我已经学会将标签视为一种糟糕的做法,但它们肯定有用途(否则它们不会在标准中实现?)。谢谢
您可以在此处使用 break
实现相同的功能,而无需使用 goto
。
我唯一一次在 C++ 中发现一个稍微令人反感的 goto
案例是在一个复杂的状态机中,开发人员非常小心不要弄乱本地状态。
通常,解析器(或更具体地说,分词器)是我进行意大利面式编码的最后一个地方——如果有的话,这需要以更实用的方式使用 C++。
我相信这是接受 goto 的极少数示例之一,但是您可以使用标志:
Token token;
bool flag = true;
while ((peekChar() != '[=10=]') && flag)
{
switch (c = nextChar())
{
case '(':
token = Token(TOKEN_LEFT_PAREN, currentLine);
flag = false;
// ... every other character, some with lots of logic
}
}
一般情况下,当我们想一次break几个作用域的时候,就意味着我们可以做子函数;类似于:
bool HandleChar(char c)
{
switch (c)
{
case '(': {
Token token = Token(TOKEN_LEFT_PAREN, currentLine);
return true;
}
// ... every other character, some with lots of logic
}
}
然后:
while (peekChar() != '[=11=]')
{
if (HandleChar(nextChar())) {
break;
}
}
// ...