2 个不稳定版本
使用旧的 Rust 2015
0.2.0 | 2018年12月4日 |
---|---|
0.1.0 | 2018年5月31日 |
#2372 in 解析器实现
用于 polonius
8KB
250 行
Polonius 解析器
Polonius 解析器是一个小型、手动编写的解析器,用于解析来自 rustc
的 非 测试用例
// program description
placeholders { 'a, 'b, 'c }
// block description
block B0 {
// 0:
loan_invalidated_at(L0);
// 1:
loan_killed_at(L2);
loan_invalidated_at(L1) / use('a, 'b);
// CFG
goto B1, B2;
}
block B1 {
use('a), outlives('a: 'b), loan_issued_at('b, L1);
}
用法
polonius_parser
链接库提供了一个名为 parse_input
的单函数,它将程序描述作为输入字符串。输入将被成功解析为 ir::Input
,或者返回一个 ParseError
。ir
结构体是一个小型、公开的数据模型。
架构
polonius_parser
被实现为一个 Lexer
,它是一个 Iterator
,从源文本中提取 Token
,以及一个 Parser
,它对这些 Tokens
进行操作。解析器是一个简单的递归下降解析器,具有 1 个令牌的预览(使用 Peekable
)。我们使用 T!
宏在整个实现中快速且清晰地引用令牌类型。
添加事实
为了将解析器扩展为新的 loan_bazzles_var_at
事实,执行以下更改
- 向
TokenKind
添加一个新的变体KwLoanBazzlesVarAt
,用于loan_bazzles_var_at
关键字(token.rs
)。 - 将关键字的缩写添加到
T!
宏中,并将新的关键字类型添加到TokenKind
的Display
实现。 - 为任何引入的新语法添加额外的令牌,例如,如果关系表示为
L1 $ V1
,添加$
。 - 在
Lexer::valid_token
(lexer.rs
)中添加一个情况kw if kw.starts_with("loan_bazzles_var_at".as_bytes()) => { ("loan_bazzles_var_at".len() as u32, T![loan_bazzles_var_at]) }
- 对于额外的令牌类型,根据需要添加情况。在我们的示例中,添加以下内容:
[b'$', ..] => (1, T![$]),
- 在
ir
数据模型中将Fact
枚举添加一个变体来表示新的事实。对我们来说,是这样:LoanBazzlesVarAt { loan: String, variable: String },
- 在
Parser::parse_fact
(parser.rs
)中为新的事实添加一个情况
如果成功,则返回T![loan_bazzles_var_at] => { /* New parsing logic here */ }
Ok(Fact::LoanBazzlesVarAt { .. })
。对于我们的示例T![loan_bazzles_var_at] => { self.consume(T![loan_bazzles_var_at])?; self.consume(T!['('])?; let loan = self.parse_parameter(T![loan])?; self.consume(T![$])?; let variable = self.parse_parameter(T![variable])?; self.consume(T![')'])?; Ok(Fact::LoanBazzlesVarAt { loan, variable }) }
自定义关系
当然,也可以通过遵循相同的步骤向词法分析器添加令牌、编写自己的解析方法并将它们添加到parse_input
中来添加自定义关系。在这种情况下,应将相应的ir
表示添加到数据模型中。
依赖关系
~2.2–4.5MB
~80K SLoC