Jos*_*ise 3 parsing compilation lexical-analysis tokenize rust
我已经编写了许多简单的标记器和递归下降解析器,因此我熟悉它们如何工作的基本概念。但是当我偶然发现以下Rust代码时,我感到很惊讶:
Option<Option<i32>>
Run Code Online (Sandbox Code Playgroud)
我们知道Rust具有>>移位运算符,因此我认为天真的令牌生成器会>>在此处输出令牌,解析器将其视为错误(因为它期望使用两个>令牌)。
但显然Rust编译器了解情况并正确处理。这里发生了什么?
>>并将其分成两个令牌,然后将其推回到令牌流中?您可以查看Rust解析库以了解其处理方式。
这是我编写的解析器,因此我对这些概念最熟悉。
令牌生成器是一个简单的逐字节解析器,它贪婪地消耗字符>>来创建DoubleRightAngle令牌。
完成标记化后,所有这些标记都被收集到向量中,并进行第二次解析。在此过程中,解析位置是一个复杂的索引,允许被“拆分”。如果需要,这允许解析器将a分解>>为两个>。特定的解析函数根据要解析的内容寻找一>>两个递归>。
Syn是另一个解析库。在这里,他们使用了一个相关的想法:每个令牌由多个span组成,每个span 代表一个字符。也就是说,该Shr结构具有一个spans: [Span; 2]字段。
看来编译器允许将多个令牌“粘合”到更大的令牌中。在解析期间,>>可以被“消耗”并替换为>:
token::BinOp(token::Shr) => {
let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1));
Some(self.bump_with(token::Gt, span))
}
token::BinOpEq(token::Shr) => {
let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1));
Some(self.bump_with(token::Ge, span))
}
token::Ge => {
let span = self.token.span.with_lo(self.token.span.lo() + BytePos(1));
Some(self.bump_with(token::Eq, span))
}
Run Code Online (Sandbox Code Playgroud)
空格周围还有其他皱纹。解析器应等效地解析这两种类型:
Option<Option<i32>>
Option < Option < i32 > >
Run Code Online (Sandbox Code Playgroud)
但是,它不应等效地解析这些表达式:
a >>= 1
a >> = 1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
105 次 |
| 最近记录: |