Parsing Rust编译器如何标记'&燃气轮机';vs'&燃气轮机&燃气轮机';非专利药?
我已经编写了许多简单的标记器和递归下降解析器,因此我熟悉它们如何工作的基本概念。但当我偶然发现以下锈迹代码时,我感到惊讶:Parsing Rust编译器如何标记'&燃气轮机';vs'&燃气轮机&燃气轮机';非专利药?,parsing,compilation,rust,tokenize,lexical-analysis,Parsing,Compilation,Rust,Tokenize,Lexical Analysis,我已经编写了许多简单的标记器和递归下降解析器,因此我熟悉它们如何工作的基本概念。但当我偶然发现以下锈迹代码时,我感到惊讶: Option<Option<i32>> 选项 我们知道Rust有一个>移位运算符,所以我认为一个简单的标记器会在这里输出一个>标记,解析器会将其视为一个错误(因为它需要两个标记) 但是很明显,Rust编译器理解这种情况并正确地处理它。这是怎么回事 标记器是否保持某种状态,不知何故知道它需要关闭一个角括号 解析器是否检查>>并将其拆分为两个令牌,
Option<Option<i32>>
选项
我们知道Rust有一个>
移位运算符,所以我认为一个简单的标记器会在这里输出一个>
标记,解析器会将其视为一个错误(因为它需要两个
标记)
但是很明显,Rust编译器理解这种情况并正确地处理它。这是怎么回事
- 标记器是否保持某种状态,不知何故知道它需要关闭一个角括号
- 解析器是否检查
并将其拆分为两个令牌,然后将其推回到令牌流中>>
- 或者完全是别的什么
- 事实上,有一个问题非常详细地描述了其中的一些内容:
事实上,Rust令牌管道(tokenizer+lexer)是一个相对简单的具有前瞻性的递归下降解析器(顺便说一句,这解释了当您编写错误代码时会出现大量语法错误。例如,忘记关闭括号,解析器将卡在该块中,抱怨该块的限制). 每个令牌都被摄取,状态在令牌之间保持,另外一个令牌被窥视以进行前瞻
当Rust遇到某件事情时,它应该为其打开一个单独的状态(例如您的示例),该状态将保持在能够精确处理该问题的状态。由于该语言的构思非常简洁,所以在引用和引用调用之外没有真正的歧义(比如
*variable.call()
-你是说(*variable.call()
还是*(variable.call())
?Rust让你明确地指定了这一点)
当涉及到像您所描述的那样的类型定义时,没有歧义,因为移位运算符不能定义在该空间中。turbofish操作符也是如此-前面的:
表示下一个类型
因此,答案是“其他东西”——严格的词法规则和有状态解析器。词法分析器不是独立于解析器的,因此它有一点上下文。此外,关于您的精确问题,只能在精确的位置找到锈蚀类型:
- 在函数签名中:显然,不能与运算符混淆
- 在
符号之后:再次不能有任何歧义,因为冒号表示将写入类型::
让x:Vec=some_iterator.collect();
- 在turbofish操作符中:
该符号的存在只是为了避免产生歧义让x=some_迭代器。collect::();
- 在特质依赖类型中:
impl trait Foo for Bar{ 依赖类型=Vec; }
关键字清楚地表明将有一个类型type
如您所见,Rust团队已经仔细设计了语法,以便语法中不存在歧义。您可以查看Rust解析库,了解它们如何处理语法 图书馆比较 毛茸茸的泡菜 这是我编写的解析器,因此我最熟悉这些概念 标记器是一个简单的逐字节解析器,它贪婪地使用标记 一旦完成标记化,所有这些标记都被收集到一个向量中,并进行第二次解析。在此过程中,解析位置是一个复杂的索引。这允许解析器根据需要将一个
>
分解为两个
。特定的解析函数根据解析的内容查找一个>
或两个递归>
标记化和解析都是使用板条箱实现的
Syn
Syn是另一个解析库。在这里,他们使用了一个相关的想法:每个标记是,每个字符一个。也就是说,结构有一个Span:[Span;2]
字段
鲁斯特
似乎编译器允许。在解析过程中:
附加点
空白处还有一条皱纹。解析器应等效地解析这两种类型:
Option<Option<i32>>
Option < Option < i32 > >
a >>= 1
a >> = 1
这种符号的存在只是为了避免产生歧义——有人说要去除涡鱼;这会如何改变你的答案?这并不能真正回答问题。许多传统的解析器都有一个完全独立于语言语义的标记化步骤,不知道是解析类型还是表达式来生成正确的标记。这似乎就是OP所讨论的标记器解析器管道。@mcarton真的有任何编程语言的lexer完全独立于解析器吗?一点背景知识通常是必要的。@Shepmaster真的吗?虽然我确实看到有人抱怨turbofish的语法,但我从未看到过一个严肃的建议来删除它。我不知道如何才能做到这一点,而不引起它所防止的许多头痛。@FrenchBoiethios可能不再有很多现代语言是纯粹的这种语言了。不。但这仍然是课程中的一种常见方法,词法分析和解析并不局限于编程语言。
a >>= 1
a >> = 1