5

词法分析器如何解决这种歧义?

/*/*/

为什么它不只是说,哦,是的,那是多行注释的开头,然后是另一个多行注释。

贪婪的词法分析器不会只返回以下标记吗?

  • /*
  • /*
  • /

我正在为 CSS 编写一个 shift-reduce 解析器,但是这个简单的注释事情妨碍了我。如果您不想了解更多背景信息,可以阅读此问题。

更新

很抱歉一开始就忽略了这个。我打算以这种形式向 CSS 语言添加扩展,/* @ func ( args, ... ) */但我不想混淆理解 CSS 但不理解我的扩展注释的编辑器。这就是为什么词法分析器不能忽略注释的原因。

4

6 回答 6

9

一种方法是让词法分析器在遇到第一个内部状态时进入不同的内部状态/*。例如,flex调用这些“开始条件”(匹配 C 风格的注释是该页面上的示例之一)。

于 2010-04-13T23:43:26.570 回答
6

最简单的方法可能是将注释作为一个单独的标记来使用——也就是说,不要发出“START COMMENT”标记,而是继续读取输入,直到您可以发出包含整个/*(anything)*/位的“COMMENT BLOCK”标记.

由于注释与可执行代码的实际解析无关,因此它们基本上可以被词法分析器剥离(或至少聚集成单个标记)。您不关心评论中的令牌匹配。

于 2010-04-13T23:42:20.407 回答
3

在大多数语言中,这并不是模棱两可的:第一个斜杠和星号用于生成“多行注释的开始”标记。后面是一个斜杠,它是注释中的纯“内容”,最后两个字符是“多行注释结束”标记。

由于前 2 个字符已被消耗,因此第一个星号也不能用于生成注释结束标记。我刚刚注意到它可能会产生第二个“评论开始”标记......哎呀,这可能是一个问题,具体取决于解析器可用的上下文数量。

我在这里说的是标记,假设对注释进行解析器级别的处理。但是这同样适用于词法分析器,其基本规则是开始,'/*'然后直到'*/'找到为止。实际上,整个评论的词法分析器级别的处理不会被第二个“评论开始”混淆。

于 2010-04-13T23:37:47.880 回答
0

使用正则表达式的算法,从字符串的开头搜索到当前位置。

if (chars[currentLocation] == '/' and chars[currentLocation - 1] == '*') {
  for (int i = currentLocation - 2; i >= 0; i --) {
    if (chars[i] == '/' && chars[i + 1] == '*') {
      // .......
    }
  }
}

这就像应用正则表达式/\*([^\*]|\*[^\/])\*/贪婪和自下而上。

于 2010-04-13T23:36:34.100 回答
0

解决此问题的一种方法是让您的词法分析器返回:

/
*
/
*
/

并让您的解析器从那里处理它。这就是我对大多数编程语言可能会做的事情,因为 / 和 * 也可以用于乘法和其他类似的事情,这对于词法分析器来说太复杂了。词法分析器实际上应该只是返回基本符号

如果令牌是什么开始过多地依赖于上下文,那么您正在寻找的很可能是一个更简单的令牌。

话虽如此,CSS 不是一种编程语言,因此 /'s 和 *'s 不能重载。真的,除了评论,它们不能用于其他任何事情。因此,除非您有充分的理由不这样做,否则我很想将整个事情作为评论令牌传递:/\*.*\*/

于 2010-04-14T00:01:29.200 回答
0

由于 CSS 不支持嵌套注释,因此您的示例通常会解析为单个标记COMMENT. 也就是说,词法分析器会将/*其视为开始注释标记,然后使用包括*/序列在内的所有内容。

于 2010-04-13T23:47:15.737 回答