词法分析器/解析器歧义

时间:2010-04-13 23:30:48

标签: lexer

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

/*/*/

它怎么不只是说,哦,是的,这是多行评论的开始,接下来是另一个多行评论。

贪婪的词法分子不会只返回以下令牌吗?

  • / *
  • / *
  • /

我正在为CSS编写一个shift-reduce解析器,然而这个简单的注释事情就在我的路上。如果您不想获得更多背景信息,可以阅读this question

更新

很抱歉首先将其删除。我打算以这种形式/* @ func ( args, ... ) */添加CSS语言的扩展,但我不想混淆一个理解CSS但不是我的扩展注释的编辑器。这就是为什么词法分子不能忽视评论。

6 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:6)

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

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

答案 2 :(得分:3)

在大多数语言中,这并不含糊:第一个斜杠和星号 消耗 以产生“多行注释开始”令牌。接下来是一个斜杠,在评论中是简单的“内容”,最后两个字符是“多行注释结束”标记。

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

我在这里谈论令牌,假设解析器级别处理注释。但这同样适用于词法分析器,其中基础规则是从'/*'开始,然后在找到'*/'之前不停止。实际上,第二个“评论开始”不会混淆整个评论的词法量级处理。

答案 3 :(得分:0)

使用regexp的算法,从字符串的开头搜索工作方式回到当前位置。

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

/
*
/
*
/

让你的解析器从那里处理它。对于大多数编程语言来说,这就是我可能做的 ,因为/'s和*'也可以用于乘法和其他类似的东西,这些都太困难了,因为词法分析器无法担心。词法分析器应该只是返回基本符号

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

话虽这么说,CSS不是一种编程语言,因此*不能超载。真的很好,除了评论之外,他们不能用于其他任何事情。所以我很想把整个事情作为评论标记传递,除非你有充分理由不这样做:/\*.*\*/