2015-07-04 48 views
0

我正在为编译器编写一个标记器。我有一个循环遍历字符,然后检查某些条件的开关。然后我需要退出这两个块来写令牌:可接受使用标签和'goto'?

Token token; 

while (peekChar() != '\0') 
{ 
    switch (c = nextChar()) 
    { 
     case '(': 
      token = Token(TOKEN_LEFT_PAREN, currentLine); 
      goto MakeToken; 
     // ... every other character, some with lots of logic 
    } 
} 

MakeToken: 
    // write the token 

这是可以接受的标签使用,还是有更好的方法吗?我已经学会认为标签只是一种可怕的做法,但是肯定必须有它们的用途(或者它们不会在标准中实施?)。谢谢。

+0

goto语句只是为了与旧的代码库的兼容性支持。我不建议goto声明或标签。使用goto语句打破了程序结构,通常一个goto语句是出现其他goto语句的原因。:) –

+0

标签是一种工具。他们既不好也不坏。如果有意义,请使用它们,如果它们没有使用,请使用它们。 – immibis

回答

2

一般来说,当我们想在一次突破几个范围,这意味着我们可以让子-功能;喜欢的东西:

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() != '\0') 
{ 
    if (HandleChar(nextChar())) { 
     break; 
    } 
} 
// ... 
+0

谢谢 - 没有想到这种方法,肯定会使代码更简单。 –

1

您可以在这里实施与break完全相同的设置,而无需使用goto

我唯一一次在C++中发现goto这个唯一有点令人反感的例子是在一个复杂的状态机中,开发人员在这个复杂的状态机中注意不要弄乱本地状态。

一般来说,解析器(或者更具体地说,一个标记器)是我最后去意大利面条编码的地方 - 如果有的话,这需要以更多功能的方式使用C++。

1

我相信这是极少数的例子之一,当转到被接受,但是你可以使用一个标志:

Token token; 
bool flag = true; 
while ((peekChar() != '\0') && flag) 
{ 
    switch (c = nextChar()) 
    { 
     case '(': 
      token = Token(TOKEN_LEFT_PAREN, currentLine); 
      flag = false; 
     // ... every other character, some with lots of logic 
    } 
} 
+0

好的,谢谢。我不知何故陷入了我的脑海,一个'休息'将允许while循环保持循环 - 谢谢! –

+0

这会 - 这就是为什么'flag'被设置为'false'! –

+0

是的,我的坏。编辑它。 – Matthew