词法分析者如何解决这种歧义?
/*/*/
它怎么不只是说,哦,是的,这是多行评论的开始,接下来是另一个多行评论。
贪婪的词法分子不会只返回以下令牌吗?
我正在为CSS编写一个shift-reduce解析器,然而这个简单的注释事情就在我的路上。如果您不想获得更多背景信息,可以阅读this question。
很抱歉首先将其删除。我打算以这种形式/* @ func ( args, ... ) */
添加CSS语言的扩展,但我不想混淆一个理解CSS但不是我的扩展注释的编辑器。这就是为什么词法分子不能忽视评论。
答案 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不是一种编程语言,因此*不能超载。真的很好,除了评论之外,他们不能用于其他任何事情。所以我很想把整个事情作为评论标记传递,除非你有充分理由不这样做:/\*.*\*/