关于解析:如何在C#中解析括号,lambda和元组表达式

How are parenthesis vs. lambda vs. tuple expressions parsed in C#

我正在编写自己的编程语言,并且在排除了其他大部分内容之后,开始解析元组/ lambda表达式。 语法非常类似于C#,但有一些区别。 我想知道C#是否可以确定是否要生成一个简单的带括号的表达式(元组或lambda),因为前瞻(k)是不确定的。

现在,我通过偷看某些指标来为解决方案共同努力,这些指标应为解析器提供有关其试图解析内容的线索。 即在@ 2处检查标识符,然后在@ 2处检查'=',','或':'(冒号用于用类型信息注释标识符)。

我的lambda语法比C#中的可用语法灵活一些,因此您可以在其中猜测标识符列表,直到不再有逗号为止,然后检查下两个标记中的')'和'=>'。

我缺少某种技巧吗?


是的,您需要无限前行,因为在某些情况下,(a, b, c, ...)可以是元组,也可以是lambda参数列表,具体取决于后面跟随的标记。还有一个歧义,因为(a.b.c.d...可以是强制类型转换中的类型表达式,也可以是带括号的正则表达式。

您可以在解析器源代码中看到C#如何解决此问题:
http://source.roslyn.io/#Microsoft.CodeAnalysis.CSharp/Parser/LanguageParser.cs,bab23e84fb31bf9e,参考

基本上,它保存当前位置并尝试解析可能的结果之一。如果解析失败,它将返回到保存的位置(也就是回溯),然后尝试下一次可能的生产。如果所有可能的生产均失败,则报告语法错误。

它似乎在两遍中运行潜在的解析。在第一遍中,它仅检查是否可以进行解析,并返回布尔值。如果此测试成功,它将运行第二遍,并在此实际构造解析树。

从理论上讲,无限制的超前处理会破坏解析器的性能,但是实际上,这可能不是一个大问题,因为它仅在特定的特定情况下才会发生,并且元组和lambda参数列表的大小通常有限。

语言设计者倾向于避免语法要求超前,因为它增加了解析器的复杂性和性能影响。但是C#的设计人员可能认为,添加漂亮的元组语法值得付出成本。