【问题标题】:What trick does Java use to avoid spaces in >>?Java使用什么技巧来避免>>中的空格?
【发布时间】:2011-02-17 23:54:20
【问题描述】:

在 Java Generic Book 中,在对比 C++ Templates 和 Java Generic 的区别时说:

在 C++ 中,会出现一个问题,因为 >> 没有空格表示 右移运算符。 Java 修复了 语法中的一个技巧问题。)

这是什么技巧?

【问题讨论】:

  • C++0x和Visual C++ 2010也有这个问题整理出来:en.wikipedia.org/wiki/C%2B%2B0x#Angle_bracket
  • 这与问题无关,但我喜欢 Scala 用来避免这个问题的技巧:List[List[String]] 而不是 List<List<String>>。问题解决了。

标签: java c++ templates generics grammar


【解决方案1】:

OpenJDK javac 解析器 JavacParser 将词法分析器标记 GTGTGTEQ (>>>=)、GTGTEQGTEQGTGTGT (>>>) 和 GTGT 按摩到标记中解析类型参数时少 '>' 字符。

这是来自JavacParser#typeArguments()的魔法sn-p:

    switch (S.token()) {
    case GTGTGTEQ:
        S.token(GTGTEQ);
        break;
    case GTGTEQ:
        S.token(GTEQ);
        break;
    case GTEQ:
        S.token(EQ);
        break;
    case GTGTGT:
        S.token(GTGT);
        break;
    case GTGT:
        S.token(GT);
        break;
    default:
        accept(GT);
        break;
    }

一看就知道确实是个小把戏,而且是在语法里:)

【讨论】:

  • 这不是公认的答案吗?它是唯一真正回答问题的人。
【解决方案2】:

这实际上在下一版本的 C++ 中得到修复。真的没有什么技巧。如果您在解析泛型或模板的过程中遇到 >> 而不是您期望的 >,那么您已经有足够的信息来生成错误消息。而且,如果您有足够的信息来生成错误消息,那么您也有足够的信息将 >> 解释为两个单独的标记:> 后跟 >。

【讨论】:

  • 这在 C++ 的情况下是不正确的,因为 A<1<<b>>c> 是具有单个序数参数 1<<b>>c 的有效泛型类型。
  • @Marcelo,但在这种情况下没有错误,因此没有必要扩展 >> 或
【解决方案3】:

这是一个简单的解析器/词法分析器破解。词法分析器通常将 >> 对识别为单个标记。然而,在解析泛型类型的过程中,解析器告诉词法分析器不要识别>>

从历史上看,C++ 并没有为了实现简单而这样做,但它可以(并且将会)使用相同的技巧来解决。

【讨论】:

    【解决方案4】:

    这并不是真正的技巧,他们只是定义了语法,使得右移标记与两个直角括号同义(因此允许该标记关闭模板)。您仍然可以创建必须用括号解决的歧义,但是在没有开发人员干预的情况下解析明确的序列。这也在 C++0x 中完成。

    【讨论】:

      【解决方案5】:

      The Java Language Specification, Third Edition 显示了完整的语法,两个移位运算符都列在InfixOp 产生式中,没有(明显的)技巧。要确定哪个操作 >、>> 或 >>> 是有意的,将由扫描仪使用lookahead 技术来决定。

      【讨论】:

      • 是的,但是第 3.2 节实际上要求将“>>”解析为一个标记,无论如何。那里有点不一致。
      猜你喜欢
      • 2014-04-09
      • 2014-10-30
      • 2018-01-30
      • 2017-05-06
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      • 2011-02-17
      • 2020-11-22
      相关资源
      最近更新 更多