Cla*_*oft 2 compiler-construction generics grammar swift ambiguous-grammar
看看以下两个表达式:
baz(Foo<Bar, Bar>(0))
baz(Foo < Bar, Bar > (0))
Run Code Online (Sandbox Code Playgroud)
不知道是什么,baz,Foo和Bar是(baz可以是一个类型或方法,Foo并且Bar可以是类型或变量),不存在多义性是否方式<代表了一个类型参数列表或小于操作.
// two different outcomes, difference shown with parentheses
baz((Foo<Bar,Bar>(0))) // generics
baz((Foo < Bar), (Bar > 0)) // less-than
Run Code Online (Sandbox Code Playgroud)
任何理智的编程语言都不应该依赖于什么baz,Foo并且Bar在解析像这样的表达式时.然而,无论我在哪里放置空格,Swift都设法消除下面的表达式的歧义:
println(Dictionary<String, String>(0))
println(Dictionary < String, String > (0))
Run Code Online (Sandbox Code Playgroud)
编译器如何管理它?而且,更重要的是,Swift语言规范中是否有任何地方.其中描述了规则.看Language Reference一下Swift书的一部分,我只发现了这一部分:
在某些构造中,具有前导
<或>可能被分成两个或更多个令牌的运算符.其余部分以相同的方式处理,可能会再次拆分.因此,不需要使用空格来消除>构造中的结束字符之间的歧义Dictionary<String, Array<Int>>.在此示例中,结束>字符不会被视为单个标记,然后可能会被误解为位移>>运算符.
certain constructs在这种情况下指的是什么?实际语法只包含一个提及类型参数的生产规则:
显式构件表达→后缀表达式
.identifiergeneric参数的子句选择
任何解释或资源将不胜感激.
感谢@Martin R,我找到了编译器源代码的相关部分,其中包含一个解释如何解决歧义的注释.
/// The generic-args case is ambiguous with an expression involving '<'
/// and '>' operators. The operator expression is favored unless a generic
/// argument list can be successfully parsed, and the closing bracket is
/// followed by one of these tokens:
/// lparen_following rparen lsquare_following rsquare lbrace rbrace
/// period_following comma semicolon
Run Code Online (Sandbox Code Playgroud)
基本上,编译器尝试解析类型列表,然后在结束尖括号之后检查令牌.如果那个令牌是
>(,>[,但不是> (,> [),它将表达式解析为泛型调用,否则将其解析为一个或多个关系表达式.
如Annotated C#一书中所述,问题在C#中以类似的方式解决.