How do parsers handle generic type parameters?

Jos*_*ise 3 c# generics parsing programming-languages recursive-descent

我正在为一种虚构的编程语言编写一个递归的体面解析器。这是一种C样式的语言,具有==,<,>,<=和> =等常用运算符,并且还具有通用功能(如C#中的那些功能)。

在C#之类的语言中,要调用通用函数,您可以编写:

someFunction<T>(x);
Run Code Online (Sandbox Code Playgroud)

我的问题是,解析器如何区分通用参数与比较运算符(<和>)。

在我看来,上面的代码可能具有以下两种含义之一:

  • 用通用参数“ T”和常规参数“ x”调用“ someFunction”
  • 计算表达式'(someFunction <T)> x',将'someFunction','T'和'x'视为正则变量

解析器将如何知道要使用哪种解释?

ric*_*ici 5

您100%正确地认为,泛型函数调用语法在包括该功能的许多语言中均不明确。

并非所有语言都使用歧义语法。在Java中,没有歧义,因为类型参数放在之前的方法名,必须由前面.SomeClass.<ArgType>genericMethod()。其它可能性包括使用不同的符号类型括号,如[]::<>!。(分别为Scala,Rust和D。Scala对数组下标使用括号。)

但是许多语言确实使用C ++ / C#语法,这是模棱两可的。每种语言都有其自己的歧义消除规则,据我所知,关于如何做到这一点尚无跨语言共识。特别是:

  • C ++要求编译器确定函数/方法/类名称是否(或可能)模板化。(ADL使这一点有些棘手,在C ++ 18中,规则进行了更改,以包括未模版的函数/方法名称可能仍被解释为已模版的情况。)

  • C#要求编译器在可能的情况下找到尖括号模板参数的结尾,然后检查下一个输入标记。如果下一个标记是一个开放的括号或不能在句法上跟随一个标记的一组标记中的一个>(例如,分号),则将模板参数照原样处理;如果没有匹配项,>或者匹配项>后跟42,则将其作为比较处理。

据我所知,使用C#定义的递归下降解析器将需要能够回溯。另一方面,C ++定义要求将名称解析混入语法分析中,这是一个不同的丑陋之处。

据我所知,您可以自由地提出自己的解决方案。如果您希望其他人使用您的语言,我鼓励您完全清楚地记录下来。(例如,我找不到用于打字稿的此类文档,但我没有使用过。)如果我要设计具有泛型的语言,我想我会使用明确的语法。但这就是我。