13

Java规范对如何标记此代码感到困惑:

ArrayList<ArrayList<Integer>> i;

规范说:

每一步都使用尽可能长的翻译,即使结果最终不会产生正确的程序,而另一个词汇翻译会。

据我了解,应用“最长匹配”规则将导致令牌:

  • 数组列表
  • <
  • 数组列表
  • <
  • 整数
  • >>
  • 一世
  • ;

这不会解析。但当然,这段代码解析得很好。

这种情况下的正确规格是什么?

这是否意味着正确的词法分析器必须是上下文无关的?使用常规词法分析器似乎不可能。

4

2 回答 2

4

根据阅读@sm4 链接的代码,看起来策略是:

  • 正常标记输入。所以A<B<C>> i;将被标记为A, <, B, <, C, >>, i, ;- 8 个标记,而不是 9 个。

  • 在分层解析期间,在解析泛型并且>需要 a 时,如果下一个标记以>-- >>>>>>=>>=>>>=-- 开头,只需>关闭并将缩短的标记推回标记流。示例:当解析器>>, i, ;在处理 typeArguments 规则时,它成功解析了 typeArguments,并且剩余的令牌流现在略有不同>, i, ;,因为第一个>>>拉出以匹配 typeArguments。

因此,尽管标记化确实正常发生,但如有必要,在分层解析阶段会发生一些重新标记化。

于 2013-05-29T01:26:59.123 回答
1

Java 10 语言规范(3.2 词汇翻译)指出:

每一步都使用尽可能长的翻译,即使结果最终不会产生正确的程序,而另一个词汇翻译会。有一个例外:如果词法转换发生在类型上下文(第 4.11 节)中,并且输入流有两个或多个连续的 > 字符后跟一个非 > 字符,那么每个 > 字符必须被转换为数值比较运算符 >.
输入字符a--b被标记化(第 3.5 节)为a, --, b,这不是任何语法正确程序的一部分,即使标记化a, -, -, b可能是语法正确程序的一部分.
如果没有 > 字符的规则,则类型中的两个连续 > 括号,例如List<List<String>>将被标记为有符号右移运算符>>,而在诸如此类的类型中的三个连续的>括号List<List<List<String>>>将被标记为无符号右移运算符>>>。更糟糕的是,四个或更多连续 > 括号的标记化类型List<List<List<List<String>>>>会模棱两可,因为 >、>> 和 >>> 标记的各种组合可以表示 >>>> 字符。

早期版本的 C++ 显然也存在这种情况,因此在两个相邻的小于 (<) 和大于 (>) 符号之间至少需要一个空格,例如vector <vector<int> >. 幸运的是,现在没有了。

于 2020-02-05T15:47:52.340 回答