我已经编写了许多简单的标记器和递归下降解析器,因此我熟悉它们如何工作的基本概念。但是当我偶然发现以下Rust代码时,我感到很惊讶:
Option<Option<i32>>
我们知道Rust有一个>>
移位运算符,所以我认为一个朴素的令牌生成器会在此处输出一个>>
令牌,解析器会认为这是一个错误(因为它期望两个{{1 }}令牌。
但是很明显,Rust编译器了解情况并正确处理。这是怎么回事?
>
并将其分解为两个令牌,这些令牌又被推回到令牌流中?答案 0 :(得分:5)
您可以查看Rust解析库以了解其处理方式。
这是我编写的解析器,所以我对这些概念最熟悉。
令牌生成器是一个简单的逐字节解析器,它贪婪地consumes the characters >>
to create a DoubleRightAngle
令牌。
完成标记化后,所有这些标记都将被收集到向量中,然后进行第二次解析。在此过程中,解析位置是allows being "split"的复杂索引。如果需要,解析器可以将>>
分解为两个>
。特定的解析函数根据要解析的内容寻找>>
或两个递归>
。
标记和解析都是使用peresil条板箱实现的。
Syn是另一个解析库。在这里,他们使用了一个相关的想法:每个令牌是composed of multiple spans,每个字符一个。即,Shr
结构具有一个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
答案 1 :(得分:1)
实际上存在一个问题,其中非常详细地描述了其中的一些问题:#13: "The parser"
现实是Rust令牌管道(tokenizer + lexer)是一个相对简单的递归下降解析器,具有超前功能(顺便说一句,它解释了您在编写错误代码时遇到的大量语法错误。例如,忘记了关闭方括号,解析器将卡在该块中,抱怨该块的限制)。每个令牌都会被提取,令牌之间的状态会保持不变,并且还会为预见目的而查看其他令牌。
当Rust遇到某种情况时,应该为其打开一个单独的状态(例如您的示例),该状态保持在状态中,以便能够精确地处理此状态。由于该语言构思精巧,因此在引用和引用调用之外没有真正的歧义(诸如*variable.call()
之类的字眼-您是指(*variable).call()
还是*(variable.call())
?Rust让您明确指定了这一点)
当涉及到您所描述的类型定义时,没有任何歧义,因为移位运算符根据定义不能在该空间中。 Turbofish运算符也是如此-::
的先例表明类型将是下一个。
因此,答案是“其他”-严格的词法分析器规则和有状态的解析器。
答案 2 :(得分:1)
词法分析器并不独立于解析器,因此它具有一些上下文。此外,关于您的确切问题,Rust类型只能在精确的位置找到:
在函数签名中:显然,与运算符不会混淆。
在:
标记之后:再次没有歧义,因为冒号指示将要写入的类型:
let x: Vec<_> = some_iterator.collect();
在turbofish运算符中:
let x = some_iterator.collect::<Vec<_>>();
该表示法仅用于不产生歧义。
在特征依赖类型中:
impl trait Foo for Bar {
type Dependent = Vec<u8>;
}
type
关键字明确表明将存在一种类型。
如您所见,Rust团队精心设计了语法,以使语法中不存在歧义。