- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编写过许多简单的分词器和递归下降解析器,因此我熟悉它们工作原理的基本概念。但是当我偶然发现以下 Rust 代码时,我感到很惊讶:
Option<Option<i32>>
我们知道 Rust 有一个 >>
移位运算符,所以我认为一个简单的分词器会在这里输出一个 >>>
标记,解析器会将其视为错误(因为它需要两个 >
标记)。
但显然 Rust 编译器了解情况并正确处理。这是怎么回事?
>>>
并将其分成两个推回 token 流的 token ?最佳答案
您可以查看 Rust 解析库以了解它们如何处理它。
这是我编写的解析器,所以我最熟悉其中的概念。
tokenizer 是一个简单的逐字节解析器,贪婪地 consumes the characters >>
to create a DoubleRightAngle
token 。
标记化完成后,所有这些标记都将收集到一个向量中,然后进行第二次解析。在此过程中,解析位置是一个复杂的索引 allows being "split" .这允许解析器在需要时将 >>
分解为两个 >
。特定的解析函数根据正在解析的内容查找一个 >>
或两个递归 >
。
标记化和解析都是使用 peresil 实现的 crate 。
Syn 是另一个解析库。在这里,他们使用了一个相关的想法:每个标记都是 composed of multiple spans , 每个字符一个。即 Shr
struct 有一个 spans: [Span; 2]
字段。
编译器似乎允许 "gluing" multiple tokens into a bigger one .在解析过程中,>>
can be "consumed" and replaced with a >
:
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))
}
空格周围还有一个额外的皱纹。解析器应该等效地解析这两种类型:
Option<Option<i32>>
Option < Option < i32 > >
但是,它不应该等效地解析这些表达式:
a >>= 1
a >> = 1
关于parsing - Rust 编译器如何标记泛型中的 '>' 与 '>>'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58065507/
我是一名优秀的程序员,十分优秀!