原始的Java泛型提案(JSR-14)要求修改Java语法以接受参数化类型中的
>>
和
>>>
,使它们能在可能出现多个闭合尖括号的上下文中使用。(我找不到关于JSR-14的有用权威链接,但Gilad Bracha的
GJ规范仍可在他的网站上找到;语法修改在第2.3节中显示。)
据我所知,这些修改从未正式纳入任何Java标准;最终,JLS8将更改描述的词法分析方法纳入其中,该方法在您的问题中引用。(请参见
JDK-8021600,该文件还复制了最初提出的复杂语法。)
Bracha等人提出的语法修改是可行的,但您可能会发现它们使其他语法修改的整合变得更加复杂。(我没有深入研究过这个问题,因此对于当前的Java语言规范来说可能并不是一个问题。但对于将来的版本可能仍然是一个问题。)
虽然词法分析上下文允许使用在 JLS 中实际使用的简单语法,但它确实给词法分析带来了困难。一种可能的方法是通过使用
无扫描器解析器 放弃词法分析; 这肯定有效,但你将无法在 Bison/Flex 模型内完成。此外,你可能会发现,支持无扫描器解析还需要对已发布的语法进行非平凡的修改。
另一个可能性是从解析器中使用词法反馈,通过合并中间规则动作(MRAs)来开启和关闭“类型上下文”标志,以便当进入或退出类型上下文时使用。( §4.11 中有一个完整的类型上下文列表,可用于查找语法中适当的位置。)如果你尝试这样做,请注意 MRA 的执行与词法分析不完全同步,因为解析器通常需要先行符号来决定是否缩减 MRA。你通常需要在语法中将 MRA 定位得比你想象的早一个符号,以便在需要时它实际上会生效。
另一种可能性是永远不将
>>
和
>>>
识别为标记。相反,词法分析器可以返回两个不同的
>
标记,其中一个在紧接着的下一个字符是
>
时使用:
>/> { return CONJUNCTIVE_GT; }
> { return INDEPENDENT_GT; }
/* These two don't need to be changed. */
>>= { return SHIFT_ASSIGN; }
>>>= { return LONG_SHIFT_ASSIGN; }
然后,您可以修改语法以识别>>
和>>>
运算符,同时允许任一形式的>
作为闭角括号:
shift_op : CONJUNCTIVE_GT INDEPENDENT_GT
long_shift_op: CONJUNCTIVE_GT CONJUNCTIVE_GT INDEPENDENT_GT
close_angle : CONJUNCTIVE_GT | INDEPENDENT_GT
gt_op : INDENPENDENT_GT /* This unit production is not really necessary */
那应该可以(虽然我没有尝试过),但它与Bison / Yacc运算符优先级机制不兼容,因为你无法为非终端声明优先级。因此,你需要使用具有显式运算符优先级规则的表达式语法,而不是带有优先级声明的模糊语法。
<List<List>>
的内容呢?” - 通过上下文。右移运算符是算术表达式的一部分,而泛型则是构造函数调用、方法签名、类型或类定义的一部分。 - Turing85>
是无关紧要的。>
就是>
,没有区别。语法正确性由解析器保证。但是,如果扫描器具有求值器,则扫描器需要上下文信息,因为 Java 的语法是上下文相关的。 - Turing85>>
是一个单词(就像>=
一样)。如果>>
被拆分成两个单词,语法将接受类似2> >3
或甚至2 >/* 这是右移* /> 3
这样的表达式,这通常是不被支持的。 - rici